.Here a*b = n and a > 1 and b > 1.For example, Alice can replace 6 with 2 or 3 or (2, 3).But he can’t replace 6 with 6 or (1, 6). But you can replace 6 with 1.
对于n个数,相当于n个局面,只要将n个局面异或起来就好了,所以我们就考虑一个数的时候的情况。
如果我们把x写成质数的幂相乘的形式就是p1^a1 * p2 ^ a2 * p3 ^ a3…*pm ^ am
sum = a1 + a2 + a3 + …. am;
操作的本质其实就是给一些指数降幂,也就是可以把sum变成(0 – > sum-1)中的任何一个数,或者变成h1 ,h2的形式,h1 + h2 = sum
h1, h2分别是两个因子对应的sum,相当于sum这个局面可以变成若干的子局面。用SG搞搞就出来了。
SG其实就是在子局面中找一个最小的未被访问过的数当做当前局面的值,如果你只想套结论的话这样就够用了。
const int maxn = 5000000 ; int sum[maxn+8] ; int prime[maxn+8] , primesize ; bool is[maxn+8] ; void make(){ memset(is , 0 , sizeof(is)) ; is[1] = 1 , sum[1] = 0 ; primesize = 0 ; for(int i = 2 ; i <= maxn ; i++){ if(! is[i]){ prime[primesize++] = i ; sum[i] = 1 ; } for(int j = 0 ; j < primesize ; j++){ if(i * prime[j] > maxn) break ; is[i * prime[j]] = 1 ; sum[i * prime[j]] = sum[i] + 1 ; if(i % prime[j] == 0) break ; } } } int sg[35] ; int dfs(int n){ if(sg[n] != -1) return sg[n] ; bool vis[35] ; memset(vis , 0 , sizeof(vis)) ; for(int i = 0 ; i < n ; i++) vis[dfs(i)] = 1 ; for(int i = 1 ; i < n ; i++) vis[dfs(i) ^ dfs(n-i)] = 1 ; int s = 0 ; while(vis[s]) s++ ; return sg[n] = s ; } int main(){ make() ; memset(sg , -1 , sizeof(sg)) ; sg[0] = 0 ; for(int i = 1 ; i <= 33 ; i++) sg[i] = dfs(i) ; int n , s , x , i ; while(scanf("%d" , &n) != EOF){ s = 0 ; for(i = 1 ; i <= n ; i++){ scanf("%d" , &x) ; s ^= sg[sum[x]] ; } if(s) puts("Alice") ; else puts("Bob") ; } return 0 ; }