正题
大意
有n堆石头,每堆石头有aiai个每次可以拿走一堆或者Y个(仅当gcd(Y,ai)=1gcd(Y,ai)=1)。拿走最后一堆石头的人就赢了,两个人都是聪明绝顶的。
解题思路
考虑构建SG函数:
SG(x)=mex(SG(x−y)(gcd(x,y)=1) υ 0)SG(x)=mex(SG(x−y)(gcd(x,y)=1)υ0)
这样我们会发现如果x是质数,那么比他小的都在集合里,那么它的SG值就是之前最大的SG值+1,这样的话质数的SG值就是递增的。
我们再考虑合数,由于质数的SG值是递增的,我们会发现其实每个合数产生不了任何新的值,那么每个合数的SG值就是它的最小质因子的SG值。
这样的话质数的SG值就是它是第几个质数
我们用素数筛来计算。
代码
#include<cstdio>
using namespace std;
int t,n,ans,a,sg[1000001],tot;
void prime()
{sg[1]=1;tot=1;//第一个特判for (int i=2;i<=1000000;i++){if (!sg[i])//没有被筛过{sg[i]=++tot;//统计第几个质数for(int j=i;j<=1000000;j+=i)if (!sg[j]) sg[j]=tot;//被最小的质因子筛掉}}
}
int main()
{scanf("%d",&t);prime();//预处理while (t--){scanf("%d",&n);ans=0;for (int i=1;i<=n;i++){scanf("%d",&a);//输入ans^=sg[a];//就SG函数的和}printf("%s\n",ans?"Alice":"Bob");//判断赢家}
}