UVALive - 7511 Multiplication Table(暴力+模拟)

题目链接:点击查看

题目大意:给出一个二维矩阵表示无限大的乘法表,每个位置的值都等于 i * j ,现在给出一个 n * m 的矩阵,现在需要判断该矩阵是否为乘法表的一个子矩阵

题目分析:训练时以为是联立方程然后高斯消元求秩,但时间复杂度顶不太住,于是就自己解方程去求秩,很显然这么庞大的代码实现写出了一堆bug,最后都到了懒得修改的地步

看了网上的题解后人都傻了,应该是正解,随便选一个位置枚举其因子作为 i 和 j ,然后 O( n * m ) 去扫一遍整个矩阵然后判断是否合法,但 1e9 内因子最多的一个数只有 1536 ,总的算下来时间复杂度也是 1e11 级别的,但最后 800ms 就过了,那就只能说明这个题目的数据应该比较难构造

然后就转换成一个简单的模拟题了,随便写写就好了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
#define double long double
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=1e5+100;

vector<tuple<int,int,int>>node;

bool check(LL x,LL y)
{
	for(auto t:node)
	{
		LL i,j,num;
		tie(i,j,num)=t;
		if((i+x)*(j+y)!=num)
			return false;
	}
	return true;
};

bool solve()
{
	if(node.empty())
		return true;
	int num,x,y;
	tie(x,y,num)=node.front();
	for(int i=1;i*i<=num;i++)
	{
		if(num%i)
			continue;
		int a=i,b=num/i;
		if(a>=x&&b>=y&&check(a-x,b-y))
			return true;
		if(b>=x&&a>=y&&check(b-x,a-y))
			return true;
	}
	return false;
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
	ios::sync_with_stdio(false);
	int w;
	cin>>w;
	int kase=0;
	while(w--)
	{
		node.clear();
		int n,m;
		cin>>n>>m;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				string s;
				cin>>s;
				if(s=="?")
					continue;
				node.emplace_back(i,j,stoi(s));
			}
		if(solve())
			cout<<"Case #"<<++kase<<": Yes"<<endl;
		else
			cout<<"Case #"<<++kase<<": No"<<endl;
	}





















   return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/108407055