题目大意
问他们的矩阵可以分成几个完全相等的块
题解
首先不考虑矩阵里的数字,我们如果想把矩阵分割成仅形状相同的块,那我们就需要找出长和宽的质因子,将矩阵分割为他们质因子的大小,比如长为10,宽为6,我们可以切长为2,宽为2,或者长为10,宽为6,或者长为5宽为3等等,这也是为什么询问次数有log2(n+m),接下来只用判断区间内的数是否相等就行了,假如我们将n分成x分,每份y个,如果x是偶数,直接对半判断(1,1)到(x/2* y,m)和((x/2+1)* y,1)到(x* y,m)是否相同就好了,如果x是奇数,判断(1,1)到(x/2* y,m)和((x/2+1)* y,1)到((x-1)* y,m)是否相同,(1,1)到(x/2* y,m)和(((x+1)/2+1)* y,1)和(x* y,m)是否相同,这样就判断了所有切割区间是否相等了,上代码
#include<cstdio>
#define MAX 1005
int prime[MAX];
int n,m;
int askn(int p,int f){
int ans,pf,fir,sec;
if(p==2){
fir=1;
sec=f+1;
printf("? %d %d %d %d %d %d\n",f,m,fir,1,sec,1);
fflush(stdout);
scanf("%d",&ans);
return ans;
}
else{
pf=f*(p>>1);
fir=1;
sec=pf+f+1;
printf("? %d %d %d %d %d %d\n",pf,m,fir,1,sec,1);
fflush(stdout);
scanf("%d",&ans);
sec=pf+1;
int ans2;
printf("? %d %d %d %d %d %d\n",pf,m,fir,1,sec,1);
fflush(stdout);
scanf("%d",&ans2);
return ans&ans2;
}
}
int askm(int p,int f){
int ans,pf,fir,sec;
if(p==2){
fir=1;
sec=f+1;
printf("? %d %d %d %d %d %d\n",n,f,1,fir,1,sec);
fflush(stdout);
scanf("%d",&ans);
return ans;
}
else{
pf=f*(p>>1);
fir=1;
sec=pf+f+1;
printf("? %d %d %d %d %d %d\n",n,pf,1,fir,1,sec);
fflush(stdout);
scanf("%d",&ans);
sec=pf+1;
int ans2;
printf("? %d %d %d %d %d %d\n",n,pf,1,fir,1,sec);
fflush(stdout);
scanf("%d",&ans2);
return ans&ans2;
}
}
int main(){
for (int i = 2; i < MAX; ++i) {
if (!prime[i]) {
prime[i] = i;
for (int j = i * i; j < MAX; j += i) {
if (!prime[j]) prime[j] = i;
}
}
}
int keepn,keepm,cntn=0,cntm=0;
scanf("%d%d",&n,&m);
keepn=n;
keepm=m;
for(int i=n;i>1;i/=prime[i]){
if(askn(prime[i],n/prime[i])){
n/=prime[i];
}
}
for(int i=m;i>1;i/=prime[i]){
if(askm(prime[i],m/prime[i])){
m/=prime[i];
}
}
n=keepn/n;
m=keepm/m;
for(int i=1;i<=n;i++)if(!(n%i))cntn++;
for(int i=1;i<=m;i++)if(!(m%i))cntm++;
printf("! %d",cntn*cntm);
}
这个大佬讲的更加清晰 大佬传送门