传送门
解析:
直接用 f [ i ] [ j ] [ t ] f[i][j][t] f[i][j][t]表示 i , j i,j i,j在第 t t t轮能否被确定。DP转移后贪心选择最小的答案就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define cs const
cs int N=305;
int s,t;
bool f[N][N][20];
string name;
bool flag;
inline bool Check_Alice(int x,int y,int t){
int num=x*y,lim=sqrt(num),xx=0,cnt=0;
for(int re i=s;i<=lim;++i){
if(num%i==0){
if(!t||!f[i][num/i][t-1]){
xx=i;
if(1<++cnt)return false;
}
}
}
return xx==x;
}
inline bool Check_Bob(int x,int y,int t){
int num=x+y,lim=num/2,xx=0,cnt=0;
for(int re i=s;i<=lim;++i){
if(!t||!f[i][num-i][t-1]){
xx=i;
if(1<++cnt)return false;
}
}
return xx==x;
}
inline bool Check_Alice_end(int x,int y){
int num=x*y,lim=sqrt(num),xx=0,cnt=0;
for(int re i=s;i<=lim;++i){
if(num%i==0){
if((t<2||!f[i][num/i][t-2])&&f[i][num/i][t]){
xx=i;
if(1<++cnt)return false;
}
}
}
return xx==x;
}
inline bool Check_Bob_end(int x,int y){
int num=x+y,lim=num/2,xx=0,cnt=0;
for(int re i=s;i<=lim;++i){
if((t<2||!f[i][num-i][t-2])&&f[i][num-i][t]){
xx=i;
if(1<++cnt)return false;
}
}
return xx==x;
}
signed main(){
// freopen("guess.in","r",stdin);
// freopen("guess.out","w",stdout);
cin>>s>>name>>t;
if(name=="Alice")flag=true;
for(int re tt=0;tt<=t;++tt,flag=!flag)
for(int re i=s;i<=300;++i)
for(int re j=s;j<=300;++j){
if(tt>=2)f[i][j][tt]=f[i][j][tt-2];
if(!f[i][j][tt])
if(flag)f[i][j][tt]=Check_Alice(i,j,tt);
else f[i][j][tt]=Check_Bob(i,j,tt);
}
for(int re sum=s*2;;++sum){
for(int re i=s,j;i<=sum/2;++i){
j=sum-i;
if(!f[i][j][t])continue;
flag=true;
for(int re k=0;k<t;++k){
if(f[i][j][k]){
flag=false;
break;
}
}
if(!flag)continue;
if((t&1)==(name=="Alice"))flag=Check_Alice_end(i,j);
else flag=Check_Bob_end(i,j);
if(flag){
cout<<i<<" "<<j<<"\n";
return 0;
}
}
}
return 0;
}