前言
博弈题,还挺有趣。
题目大意
一个正整数序列,gcd为1。
两人轮流操作,每次选择一个>1的数将其-1。
然后d是新序列的gcd,将所有数除以d。
不能操作者输。
结论
初始gcd为1,一定存在至少一个奇数。
如果有奇数个偶数,先手是一定必胜的。
先手先操作一个偶数变成奇数(此时场上就至少2个奇数了,然后此时有偶数个偶数),然后看后手表演:
后手将一个奇数变成偶数,先手就再把这个偶数变成奇数。
后手将一个偶数变成奇数,先手可以把另一个偶数变成奇数。
可以发现中途任意时刻序列的gcd不会为偶数,因此不会改变序列每个元素的奇偶性。
这样下去先手就胜了。
那后手怎么胜呢?
有偶数个偶数吗?
似乎不太对,如果只有一个奇数的,先手就会上来先操作这个奇数,让场上出现偶gcd。
这种情况(偶数个偶数,且只有1个奇数)递归即可。
其余情况直接出解。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
int a[maxn];
int i,j,k,l,t,n,m;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
bool solve(){
int i;
fo(i,1,n)
if (a[i]%2==1){
/*if (a[i]==1){
if (n%2==0) return 1;
else return 0;
}*/
if (a[i]==1) return 0;
a[i]--;
break;
}
int d=a[1];
fo(i,2,n) d=gcd(d,a[i]);
fo(i,1,n) a[i]/=d;
int t=0,l=0;
fo(i,1,n)
if (a[i]%2==0) t^=1;else l++;
if (!t&&l==1) return solve()^1;
else if (t) return 0;
else return 1;
}
int main(){
scanf("%d",&n);
fo(i,1,n){
scanf("%d",&a[i]);
k=a[i];
if (k%2==0) t^=1;else l++;
}
if (!t&&l==1){
if (solve()) printf("First\n");else printf("Second\n");
return 0;
}
if (t) printf("First\n");else printf("Second\n");
}