hdu 7061 GCD Game
题意:
-
n n n 个数
A l i c e Alice Alice 和 B o b Bob Bob 轮流操作
每次操作从 n n n 个数里面取出一个数和 x x x,返回 g c d ( a i , x ) ( 1 < = x < a i ) gcd(a_i,x) (1<=x<a_i) gcd(ai,x)(1<=x<ai)
最后不能操作的人失败
分析:
-
明显是博弈题
每次是对 a i a_i ai 的因子进行取舍,不妨将 a i a_i ai 表示成质因子的幂次的乘积形式: a i = 2 x 1 ∗ 3 x 2 ∗ 5 x 3 ∗ . . . a_i=2^{x_1}* 3^{x_2}*5^{x_3} * ... ai=2x1∗3x2∗5x3∗...
当所有 a i a_i ai 被取成 1 1 1 时,即 a i a_i ai 的质因子个数为 0 0 0 时,游戏失败
故将 a i a_i ai 所有质因子的幂次之和 ( x 1 + x 2 + x 3 + . . . ) (x_1+x_2+x_3+...) (x1+x2+x3+...) 看为石子数,剩下的就是 N i m Nim Nim 博弈了,和求 a i a_i ai 的质因子的幂次之和
-
这题是一道理解欧拉筛过程的好题:欧拉筛过程中加上一个数组存一下,就可以得出 a i a_i ai 的质因子的幂次之和
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7+5;
int num[N]; //num[i]维护质因子个数
int b[N], pri[N], tot;
inline void isprime(int n=N-5)
{
b[0]=b[1]=1;
for(int i=2;i<=n;i++)
{
if(!b[i]) pri[++tot]=i, num[i]=1;
for(int j=1;pri[j] <= n/i;j++)
{
b[pri[j]*i] = 1;
num[pri[j]*i] = num[i]+1;
if(i%pri[j]==0) break ;
}
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
isprime();
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int ans=0;
for(int i=1;i<=n;i++)
{
int a;
cin>>a;
ans ^= num[a];
}
if(ans!=0) cout<<"Alice\n";
else cout<<"Bob\n";
}
return 0;
}