题目链接在这里:G-Deleting Divisors_牛客竞赛博弈专题班组合游戏基本概念、对抗搜索、Bash游戏、Nim游戏习题 (nowcoder.com)
这道题一道比较明显的思路是使用sg函数,因为可以看到比较明显的一个状态推到另一个状态的过程。在考场上的话应该想到的是通过sg函数打表找规律来做。
1 #include "bits/stdc++.h" 2 using namespace std; 3 const int MAX=100005; 4 int n; 5 int sg[MAX]; 6 int main(){ 7 int i,j; 8 memset(sg,0,sizeof(sg)); 9 for (i=2;i<=1000;i++) 10 for (j=2;j*j<=i;j++) 11 if (i%j==0){ 12 if (sg[i-j]==0 || sg[i-i/j]==0) 13 sg[i]=1; 14 } 15 for (i=1;i<=1000;i++) 16 cout<<i<<" : "<<sg[i]<<endl; 17 return 0; 18 }
下面是正解:
通过分解质因数然后观察可以看出这个和奇偶性是有关系的,我们就来考虑两种状态:
1. 如果当前数为一个奇数,那么它的所有因子一定是奇数,所以它减掉一个因子一定是一个偶数,即它的下一状态要么是已经寄了,要么是第二状态。
2. 如果当前数是一个偶数,并且不为2的次幂,那么它一定能转成第一状态,因为假设当前数为m*2^k,那么我们减去一个m,剩下的数必定为m*(2^k-1),两个奇数相乘必定是奇数。
综上,我们看到,在2状态下必胜,只有在1状态下在会输。
现在我们来看一下2的次幂怎么做,2的次幂要么转成1,要么转成2,因为转成2必胜,所以当前操作肯定是为了转成1,所以就是每次除以2,这就要看2上面的指数的奇偶了。
所以我们判断里两个,对于非2的次幂奇数必败,偶数必胜。对于2的次幂,指数奇数必败,指数偶数必胜。
1 #include "bits/stdc++.h" 2 using namespace std; 3 int t; 4 int n; 5 int check(int x){ 6 int i,j,an=0; 7 while (x%2==0){ 8 an++; 9 x/=2; 10 } 11 return x==1?an:0; 12 } 13 int main(){ 14 int i,j,an; 15 scanf("%d",&t); 16 while (t--){ 17 scanf("%d",&n); 18 if (n%2==1) cout<<"Bob"<<endl; 19 else{ 20 an=check(n); 21 if (an==0 || an%2==0) cout<<"Alice"<<endl; 22 else cout<<"Bob"<<endl; 23 } 24 } 25 return 0; 26 }
未来是什么样,未来会发生什么,谁也不知道。
但是我知道,
起码从今天开始努力,
肯定比从明天开始努力,
要快一天实现梦想。
千里之行,始于足下! ——《那年那兔那些事儿》