版权声明:本博客内容基本为原创,如有问题欢迎联系,转载请注明出处 https://blog.csdn.net/qq_41955236/article/details/84403613
题目链接:https://vj.e949.cn/64651dcc714b96f75b1cc533bde4ff55?v=1542794579
题意:
有一个无限大乘法表,现在给你这个乘法表上一块n*m的区域,但是有一些数字可能被遗忘,问你这样一块数字能否在这个乘法表上被找到。
做法:
如果有两个数字已知,可以用二元一次方程的来推出左上角是几行几列,那么只要验证了所有的数字是否合法,以及这一块数字的位置是否超出其原有的位置即可。
如果只有一个数字已知,那么只要枚举它的因子,可以找到行列都小于等于当前它的行列的也就算满足条件。
代码有点 繁重
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000005;
const double eps=1e-9;
struct node{
ll a,b,v;
}e[maxn];
char s[15];
ll x1,Y1,x2,y2;
int flag;
void qiu(ll a,ll b,ll c,ll &ansf,ll &anss){
if(a==0){
if(c%b==0){
ansf=-(c/b);
}
return ;
}
double deta=sqrt(1.0*(b*b-4*a*c));
ll ans1=(-b+deta)/(2*a),ans2=(-b-deta)/(2*a);
int flag1=0;
if(a*ans1*ans1+b*ans1+c==0&&ans1>0){
flag1=1;
ansf=ans1;
}
if(a*ans2*ans2+b*ans2+c==0&&ans2>0){
if(flag1) anss=ans2;
else ansf=ans1;
}
}
int deal(){
ll aa=e[2].a-e[1].a,bb=e[2].b-e[1].b,ans1=0,ans2=0,v1=e[1].v,v2=e[2].v;
qiu(aa,v1-v2+aa*bb,v1*bb,ans1,ans2);
if(ans2!=0){
int rans=2;
x1=v1/ans1-e[1].a+1,Y1=ans1-e[1].b+1;
if(x1<=0||Y1<=0)
rans--;
x2=v1/ans2-e[1].a+1,y2=ans2-e[1].b+1;
if(x2<=0||y2<=0)
rans--;
else {
if(rans==1){
x1=x2,Y1=y2;
}
}
return rans;
}
else if(ans1!=0){
x1=v1/ans1-e[1].a+1,Y1=ans1-e[1].b+1;
if(x1<=0||Y1<=0) return 0;
return 1;
}
return 0;
}
int ck(ll a,ll b,ll v,ll x,ll y){
return v==(x+a-1)*(y+b-1);
}
int main(){
int t,n,m,cas=0;
cin>>t;
while(t--){
int now=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%s",s);
if(s[0]!='?'){
++now;
e[now].a=i,e[now].b=j,e[now].v=(ll)atoi(s);
}
}
}
flag=0;
if(now>=2){
int cnt=deal();
if(cnt){
int flag1=0,flag2=1;
for(int i=3;i<=now;i++){
if(!ck(e[i].a,e[i].b,e[i].v,x1,Y1)){
flag1=1;
break;
}
}
if(cnt==2){
flag2=0;
for(int i=3;i<=now;i++){
if(!ck(e[i].a,e[i].b,e[i].v,x2,y2)){
flag2=1;
break;
}
}
}
flag=flag1&flag2;
}
else {
flag=1;
}
}
else if(now==1){
int up=sqrt(e[1].v+1),x=e[1].a,y=e[1].b,v=e[1].v,flags=1;
for(int i=1;i<=up;i++){
if(v%i==0){
int z=v/i;
if(x<=i&&y<=z||y<=i&&x<=z) {
flags=0;
break;
}
}
}
flag=flags;
}
printf("Case #%d: ",++cas);
if(flag){
printf("No\n");
}
else printf("Yes\n");
}
return 0;
}