zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Bootstrap/Font-Awesome/sweetalert插件
    网络编程
    异常处理
    再看属性查找
    元类
    面向对象中的一些内置方法
    反射
    内置函数
    绑定方法与非绑定方法
    多态与鸭子类型
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15133964.html
Copyright © 2011-2022 走看看