题意
有 n 个整数,其中第 i 个数为 Ai。这些数字的 gcd 为 1。两人轮流操作,每次操作把一个大于 1 的数减 1,并把所有数除以所有数的最大公约数,最后无法操作者输,求是否先手必胜
题解
特判n=1
定义3个状态:
1.有奇数个偶数,至少一个奇数
2.有偶数个偶数,至少两个奇数
3.有偶数个偶数,有一个奇数
首先呢,由于初始值gcd为1,所以1.2.3.一定已经涵盖了所有开始和中途可能出现的状态
终止状态就是全部是1,也就是2.
在1.,我们可以令一个偶数-1,那么就可以转移到2.
在2.,无论令偶数-1或奇数-1,都只能转移到1.
综上,1必胜2必败
在3.时,如果让偶数-1,转移到1.(必胜),所以只能让奇数-1,然后暴力的除掉gcd,递归处理即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int N=1e6+5;
typedef long long ll;
int n,a[N];
int gcd(int x,int y){
if(!y)
return x;
return gcd(y,x%y);
}
bool dfs(int a[]){
if(n==1)
return false;
int cnte=0,cnto=0,poso=-1;
for(int i=1;i<=n;i++)
if(a[i]%2)
cnto++,poso=i;
else
cnte++;
if(cnte%2)
return true;
else if(cnto>1)
return false;
else{
if(a[poso]==1){
ll tmp=0;
for(int i=1;i<=n;i++)
tmp+=a[i]-1;
return tmp%2;
}
a[poso]--;
int g=a[1];
for(int i=2;i<=n;i++)
g=gcd(g,a[i]);
for(int i=1;i<=n;i++)
a[i]/=g;
return dfs(a)^1;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
puts(dfs(a)?"First":"Second");
}