GCD Game(nim博弈)

GCD Game(nim博弈)

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

题意:
爱丽丝和鲍勃正在玩游戏。
他们轮流操作。有n个数字,a1,a2,一每一次,玩家分三步进行游戏。
1.任意选择一个数字ai。
2.任意选择另一个数字x(1≤x<ai)。
3.将数字ai替换为gcd(ai,x)。这里,gcd(u,v)指的是u和v的最大公约数。
当一名玩家一步也不能移动时,他/她将输掉比赛。爱丽丝先移动,她让你告诉她,如果双方都玩得很好,谁将赢得比赛。

以下思路来自这位大佬(直接粘过来的)

思路 实际上这就是Nim博弈。首先注意到gcd的本质。不妨设
a=p1x1p2x2…pnxn,b=p1y1p2y2…pnyn
则gcd(x,y)=p1min(x1,y1)p2min(x2,y2)…pnmin(xn,yn)考虑把每个ai唯一分解为若干个质数幂次的乘积。因为每次x是任意选的,且gcd(ai,x)是ai的因子,所以当前玩家可以直接选择当前ai的任意因子,这样很自然的就可以把初始ai的质因子累积个数看做石子数,ai变成1则不能操作等价于此时ai的每个质因子次数为0,也就是石子数为0。用欧拉筛预处理出每个数的质因子个数,对于输入直接查询sg值然后求异或和进行普通nim博弈即可。

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=1e7+10;
int p[N],book[N],num[N],cnt;
void init()
{
	int i,j;
	for(i=2;i<=N;i++)
	{
		if(!book[i])
		{
			p[++cnt]=i;
			num[i]=1;
		}
		for(j=1;j<=cnt&&i*p[j]<=N;j++)
		{
			book[i*p[j]]=1;
			num[i*p[j]]=num[i]+1;
			if(i%p[j]==0)
			break;
		}
	}
}
int main()
{
	int t,n,a;
	init();
	scanf("%d",&t);
	while(t--)
	{
		
		scanf("%d",&n);
		int sum=0;
		while(n--)
		{
			scanf("%d",&a);
			sum^=num[a];
		}
		if(!sum)
		printf("Bob\n");
		else
		printf("Alice\n");
	 } 
	return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值