2021“MINIEYE杯”中国大学生算法设计超级联赛(8)1006. GCD Game(Nim博弈)

Problem Description

Alice and Bob are playing a game.

They take turns to operate. There are n numbers, a1 , a2 , ... , an. Every time, the player plays in 3 steps.
1.Arbitrarily chooses one number ai.
2.Arbitrarily chooses another number x(1≤x<ai).
3. Replace the number ai with gcd(ai,x). Here, gcd(u,v) refers to the Greatest Common Divisor of u and v.

When a player can not make a single move he/she loses the game. Alice moves the first and she asks you to tell her who will win the game if both player play optimally.

Input

The first line contains a number T(1≤T≤100), the number of testcases.

For each testcase, there are two lines.
The first line contains one number n(1≤n≤106).
The second line contains n numbers a1 , a2 , ... , an(1≤ai≤107).

It is guaranteed that for all testcases, ∑n≤106.

Output

For each testcase, output the answer in one line. If Alice will win the game, print "Alice", otherwise print "Bob".

Sample Input

2
1
1
1
2

Sample Output

Bob
Alice

实际上这就是Nim博弈。首先注意到gcd的本质。不妨设(a = p_1^{x_1}p_2^{x_2}...p_n^{x_n}, b = p_1^{y_1}p_2^{y_2}...p_n^{y_n}),则(gcd(x, y) = p_1^{min(x_1, y_1)}p_2^{min(x_2, y_2)}...p_n^{min(x_n, y_n)})考虑把每个ai唯一分解为若干个质数幂次的乘积。因为每次x是任意选的,且(gcd(a_i, x))是ai的因子,所以当前玩家可以直接选择当前ai的任意因子,这样很自然的就可以把初始ai的质因子累积个数看做石子数,ai变成1则不能操作等价于此时ai的每个质因子次数为0,也就是石子数为0。用欧拉筛预处理出每个数的质因子个数,对于输入直接查询sg值然后求异或和进行普通nim博弈即可。

#include<bits/stdc++.h> 
using namespace std;
const int maxn=1e7+10;
int sg[maxn],primes[maxn];
int m=0; 
void getprimes(){
    sg[1]=0;
    for(int i=2;i<=maxn;i++){
        sg[i]=1;
    }
    for(int i=2;i<=maxn;i++){
        if(sg[i]==1) {sg[i]=1;primes[++m]=i;}
        for(int j=1;j<=m&&primes[j]*i<=maxn;j++){
            sg[primes[j]*i]=sg[i]+1;
            if(i%primes[j]==0)break;
        }
    }
}
int main(){
    getprimes();
    int T;
    cin>>T;
    while(T--){
        int n,x;
        cin>>n;
        int ans=0;
        int one=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            if(x==1) one++;
            ans^=sg[x];
        }
        if(one==n) puts("Bob");
        else if(ans==0) puts("Bob");
        else puts("Alice");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lipoicyclic/p/15133964.html