题意:询问a,b,n。每次可以a+1或b+1,保证a^b<=n,不能操作者输。问先手是否赢?
n<=1e9.
标程:
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 using namespace std; 5 int read() 6 { 7 int x=0,f=1;char ch=getchar(); 8 while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} 9 while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); 10 return x*f; 11 } 12 typedef long long ll; 13 const int N=40001; 14 int n,m,top[N],f[N][32],tot,x,y,ans; 15 int main() 16 { 17 n=read();m=read();int ss=sqrt(n); 18 memset(f,1,sizeof(f));//边界态 19 f[ss+1][1]=((n-ss-1)&1); 20 for (int i=ss;i>=2;i--,tot=0) 21 { 22 for (ll g=i;g<=n;g*=i) tot++; 23 for (int j=tot;j>=1;j--) f[i][j]=(!f[i+1][j]||!f[i][j+1]); 24 } 25 while (m--) 26 { 27 x=read();y=read(); 28 if (x>ss) ans=((n-x)&1);else ans=f[x][y]; 29 puts(ans?"Yes":"No"); 30 } 31 return 0; 32 }
易错点:注意考虑当n>sqrt(n)的情况,因为是链型递推,可以直接以奇偶性来判断。
题解:博弈
对于n<=sqrt(n)的考虑,转移式子为f[i][j](起点于i,j,先手是否能赢)=(!f[i+1][j]||!f[i][j+1]).
注意一下边界。