UVALive 7511 Multiplication Table

题意; 给出一个矩阵,询问是否能从乘法表中找出他的位置

思路:

对于每个数字 如果他可以拆解为 x1 *y1  x2*y2那么他必定有可能出现在X1行Y1列, X2行Y2列。那么如果已知了两个数字,那我们就直接可以确定

他在哪个矩阵部分。 那么我们就可以用这个矩阵验证已知的每一项。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e3 + 50;
ll prim[10][N], a[N][N];
ll x[10], y[10], tot[10], cnt;
char s[N];

ll get(){
	ll num = 0;
	if(s[0] == '?') return -1;
	for(int i = 0; i < strlen(s); i++) num = num * 10 + s[i] - '0';
	return num; 
}

void split(ll num){
	for(ll i = 1; i * i <= num; i++){
		if(num % i == 0) {
			prim[cnt][++tot[cnt]] = i;
			prim[cnt][++tot[cnt]] = num / i;
		}
	}
}

int main(){
	int T;
	scanf("%d", &T);
	for(int kase = 1; kase <= T; kase++){
		ll n, m;
		cnt = 0;
		memset(tot, 0, sizeof(tot));
		memset(x, 0, sizeof(x));
		memset(y, 0, sizeof(y));
		memset(a, 0, sizeof(a));
		memset(prim, 0, sizeof(prim));
		scanf("%lld%lld", &n, &m);
		for(ll i = 1; i <= n; i++){
			for(ll j = 1; j <= m; j++){
				scanf("%s", s);
				a[i][j] = get();
				if (cnt == 2) continue;
				if(a[i][j] != -1) {
					cnt++;
					x[cnt] = i, y[cnt] = j;
					split(a[i][j]);
				}		
			}
		}
		printf("Case #%d: ", kase);
		int ok = 1, tx = 0;
		if(cnt == 0) {
			puts("Yes");
			continue;
		}else if(cnt == 1) {
			ok = 0;
			ll num = a[x[1]][y[1]];
			for(ll i = 1; i <= tot[1]; i++) {
			//	cout << prim[1][i] << " " << num / prim[1][i] << endl;
				if(prim[1][i] - x[1] + 1 > 0 && num / prim[1][i] - y[1] + 1 > 0) ok = 1;
			//	cout << ok << endl;
			}
		}else {
			for(ll i = 1; !tx && i <= tot[1]; i++) {
				for(ll j = 1; !tx && j <= tot[2]; j++) {
					ll num1 = a[x[1]][y[1]], num2 = a[x[2]][y[2]];
					ll x1 = prim[1][i], y1 = num1 / prim[1][i], x2 = prim[2][j], y2 = num2 / prim[2][j];
					if(x1 - x2 == x[1] - x[2] && y1 - y2 == y[1] - y[2]) {
						tx = i;
					}	
				}
			}
			ll num = a[x[1]][y[1]];
			if(prim[1][tx] - x[1] + 1 < 1 || num / prim[1][tx] - y[1] + 1 < 1) ok = 0;
			else {
				ll zx = prim[1][tx] - x[1] + 1, zy = num / prim[1][tx] - y[1] + 1;
				for(ll i = 1; i <= n; i++){
					for(ll j = 1; j <= m; j++){
						ll num = (zx + i - 1) * (zy + j - 1);
						if(a[i][j] != -1 && a[i][j] != num) ok = 0;
 					}
				} 
			}
		}
		if(ok) puts("Yes");
		else puts("No");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值