[agc010d] Decrementing - 博弈 结论题 -

这题真的不会,不知道正解是怎么想出的 (

首先容易想到当出现一个1的时候,以后的gcd就全是1了,所以后面的操作就只有减1,没有除法。

这个时候,如果轮到i走,还剩奇数轮,他就胜了,反之他就败了。

更具体地,还剩奇数轮等于说是还剩奇数个偶数,所以我们来关注一波奇偶性(偶数的个数记为cnt[0],奇数的个数记为cnt[1])。

由于题目保证一开始g=1,所以黑板上至少混入了一个奇数。

至于偶数的个数,我们分两类:

A.有奇数个偶数。

此时先手美滋滋啊,已经处于有利局面,他只要稳住,使得每次轮到他的时候依然还剩奇数个偶数那就稳赢了。

显然可以随手把一个偶数-1,变成奇数。

此时至少有两个奇数了,且cnt[0]由奇数变为了偶数(g此时不可能为偶数,因此(奇数/g)还是奇数,(偶数/g)还是偶数,除法不影响奇偶性)。

轮到后手,他不管怎么搞,

要么把偶数变成奇数,此时先手直接把其它某个偶数也变成奇数(因为cnt[0]>=2,所以肯定可以这样)。

要么把奇数变成偶数,此时先手直接把这个数再变回奇数(因为这个数>=2,所以肯定可以这样)。

这样,又符合了有利条件,一直操作到出现了一个1,先手就稳了。

B.有偶数个偶数。

似乎很容易想到这时是后手必胜。

先手把一个奇数变为偶数或者把一个偶数变为奇数,这样后手面临的局势和A情况一样,他就成了winner。

但是怎么WA了呢??

仔细检查,原来此时先手把奇数变为偶数后g不一定为奇数了!!这样问题就复杂了,需要我们进一步分类讨论。

如果cnt[1]>=2,那么先手再怎么搞,顶多减掉一个奇数,但还是有奇数幸存下来了,这样g就还是奇数,后手稳赢。

所以只要看cnt[1]=1的情况就可以了。这个时候先手只能寄希望于这个唯一的奇数了,他肯定会怒改奇数,这样g就是偶数了,

局面就会重新变得生机盎然。不管他能不能赢,我们至少看到,这样一来,其实只是将所有数除以g,继续进行和原来类似的子问题,而且后手先手交换了身份,进行新一轮博弈。我们递归下去,直到分出胜负即可。

#include <cstdio>
#define rep(i,j,k) for (i=j;i<=k;i++)
using namespace std;
const int N=1e5+5;
int n,i,ans,a[N],cnt[2];
int gcd(int a,int b) {
	int c=a%b;
	while (c) { a=b; b=c; c=a%b; }
	return b;
}
int solve()
{
	int i,ret,g,pos=0;
	cnt[0]=cnt[1]=0;
	rep(i,1,n) {
		cnt[a[i]%2]++;
		if (a[i]%2 && a[i]>1) pos=i;
	}
	if (cnt[0]%2==0 && cnt[1]==1 && pos) {
		a[pos]--; g=a[1];
		rep(i,2,n) g=gcd(g,a[i]);
		rep(i,1,n) a[i]/=g;
		ret=solve()^1;
	}
	else ret=cnt[0]%2;
	return ret;
}
int main()
{
	scanf("%d",&n);
	rep(i,1,n) scanf("%d",&a[i]);
	ans=solve();
	if (ans) printf("First\n");
	else printf("Second\n");
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值