传送门:https://www.luogu.org/problemnew/show/P4459
提答题啊。。题目真骚。我们试着分析一下
现在假设ALICE开始
ALICE:不知道。。
现在BOB得到哪些信息了呢?
有至少两个整数能被nm整除,不然ALICE咋会说不确定呢。。。
假设下一步BOB:不资道~~~
现在我们又得到哪些信息了呢?
BOB知道两数之和,那么BOB可以列举出一些可能的答案
BOB既然不资道那么在这些可能的答案中有至少两个满足ALICE的条件
好像dp啊。。。
我们假设表示Alice开始后的第p个询问之后alice和bob都回答不资道(Alice算第一个)i,j是否满足
中是否只有一个整数被i*j整除是的话f(p,i,j)=0;否则f(p,i,j)=1;
如果f(p-1,i,j)等于0那么f(p,i,j)=0;
若p%2==0
列举出所有和等于i+j 且数大于s的情况判断这些答案满足的个数大于1可以,否则不行
若p%2==1
列举所有乘积等于i*j且数大于s的情况判断这些答案满足的个数大于1可以,否则不行
我们从1开始模拟他们询问与回答
如果我们在算到其中一个人的时候他的答案变唯一了那么ta知道了
接下来我们要看对方是否也会知道
我们把对方剩余的可能解进行分解,看答案为一的个数是否为1
如果是,那么他也知道了,如果不知道,那么他永远不会知道。。
以上是ALICE开始的情况BOB开始的话请自行列举~~
提答题,,所以我写了四个程序(用文件操作链接)。跑起来好慢。。25个数据跑完要0.5h
ALICE开始,模拟两人对答过程:
#include <bits/stdc++.h> using namespace std; #define rep(i,j,k) for(i=j;i<=k;++i) #define dow(i,j,k) for(i=j;i>=k;--i) const int N=500; int s,n,m,dp[N+10][N+10][N+10]; bool f(int p,int x,int y){ if(dp[p][x][y]!=-1)return dp[p][x][y]; if(p==1){ int i=s,cnt=0; for(;i*i<=x*y;++i) if(x*y%i==0)++cnt; return dp[p][x][y]=(cnt>1); }if(f(p-1,x,y)==0)return dp[p][x][y]=dp[p-1][x][y]; if(p%2==0){ int i,cnt=0; rep(i,s,(x+y>>1)) if(f(p-1,i,x+y-i))++cnt; return dp[p][x][y]=(cnt>1); }else{ int i,cnt=0; for(i=s;i*i<=x*y;++i)if(x*y%i==0 && f(p-1,i,x*y/i))++cnt; return dp[p][x][y]=(cnt>1); } } int main(){freopen("in.txt","r",stdin);freopen("o.txt","w",stdout); scanf("%d%d%d",&s,&m,&n); int i=1,j,k,ct=0;rep(i,1,N)rep(j,1,N)rep(k,1,N)dp[i][j][k]=-1; for(i=s;i*i<=m*n;++i)if(m*n%i==0)++ct; if(ct==1){ printf("0");return 0; } i=1; while(i<=500){ if(i%2==0){ int j,cnt=0; for(j=s;j*j<=n*m;++j)if(n*m%j==0 && f(i,j,n*m/j))++cnt; if(cnt==1){ int c2=0; rep(j,s,(n+m)>>1){ int c3=0,jj; for(jj=s;jj*jj<=j*(n+m-j);++jj) if(j*(n+m-j)%jj==0 &&f(i,jj,j*(n+m-j)/jj))++c3; c2+=(c3==1); } if(c2==1) printf("%d",i);else printf("-1"); return 0; } }else{ int j,cnt=0; rep(j,s,(n+m>>1))if(f(i,j,n+m-j))++cnt; if(cnt==1){ int c2=0; for(j=s;j*j<=n*m;++j)if(n*m%j==0){ int jj,c3=0; rep(jj,s,(j+n*m/j)/2)if(f(i,jj,j+n*m/j-jj))++c3; c2+=(c3==1); } if(c2==1) printf("%d",i); else printf("-1"); return 0; } } ++i; } }
BOB开始,模拟两人对答过程:
#include <bits/stdc++.h> using namespace std; #define rep(i,j,k) for(i=j;i<=k;++i) #define dow(i,j,k) for(i=j;i>=k;--i) const int N=500; int s,n,m,dp[N+10][N+10][N+10]; bool f(int p,int x,int y){ if(dp[p][x][y]!=-1)return dp[p][x][y]; if(p==1){ int i=s,cnt=0; for(;i+i<=x+y;++i) ++cnt; return dp[p][x][y]=cnt>1; }if(f(p-1,x,y)==0)return dp[p][x][y]=0; if(p%2==1){ int i,cnt=0; rep(i,s,(x+y>>1)) if(f(p-1,i,x+y-i))++cnt; return dp[p][x][y]=cnt>1; }else{ int i,cnt=0; for(i=s;i*i<=x*y;++i)if(x*y%i==0 && f(p-1,i,x*y/i))++cnt; return dp[p][x][y]=cnt>1; } } int main(){ freopen("in.txt","r",stdin);freopen("o.txt","w",stdout); scanf("%d%d%d",&s,&m,&n); int i=1,j,k;rep(i,1,N)rep(j,1,N)rep(k,1,N)dp[i][j][k]=-1; i=1; if(m==n && m==s){ printf("0");return 0; } while(i<=500){ if(i%2==1){ int j,cnt=0; for(j=s;j*j<=n*m;++j)if(n*m%j==0 && f(i,j,n*m/j))++cnt; if(cnt==1){ int c2=0; rep(j,s,(n+m)>>1){ int c3=0,jj; for(jj=s;jj*jj<=j*(n+m-j);++jj)if(j*(n+m-j)%jj==0 &&f(i,jj,j*(n+m-j)/jj))++c3; c2+=(c3==1); } if(c2==1) printf("%d",i);else printf("-1"); return 0; } }else{ int j,cnt=0; rep(j,s,(n+m>>1))if(f(i,j,n+m-j))++cnt; if(cnt==1){ int c2=0; for(j=s;j*j<=n*m;++j)if(n*m%j==0){ int jj,c3=0; rep(jj,s,(j+n*m/j)/2)if(f(i,jj,j+n*m/j-jj))++c3; c2+=(c3==1); } if(c2==1) printf("%d",i); else printf("-1"); return 0; } } ++i; }printf("-1"); }
计算ALICE开始的答案
#include <bits/stdc++.h> using namespace std; #define rep(i,j,k) for(i=j;i<=k;++i) #define dow(i,j,k) for(i=j;i>=k;--i) int s,t; int main(){ scanf("%d%d",&s,&t); int p,x,y; rep(p,(s+s),700){ rep(x,s,(p>>1)){ freopen("in.txt","w",stdout); printf("%d %d %d\n",s,x,p-x); fclose(stdout); system("a.exe"); freopen("o.txt","r",stdin); scanf("%d",&y); fclose(stdin); if(y==t){ freopen("ans.txt","w",stdout); printf("%d %d",x,p-x); return 0; } } } }
计算BOB答案
#include <bits/stdc++.h> using namespace std; #define rep(i,j,k) for(i=j;i<=k;++i) #define dow(i,j,k) for(i=j;i>=k;--i) int s,t; int main(){ scanf("%d%d",&s,&t); int p,x,y; rep(p,(s+s),700){ rep(x,s,(p>>1)){ freopen("in.txt","w",stdout); printf("%d %d %d\n",s,x,p-x); fclose(stdout); system("b.exe"); freopen("o.txt","r",stdin); scanf("%d",&y); fclose(stdin); if(y==t){ freopen("ans.txt","w",stdout); printf("%d %d",x,p-x); return 0; } } } }