首先考慮最簡單的情況,如果有一個數是 \(1\),那麼第二步沒有作用,勝負是固定的,先判掉。
然後發現題目給了一個很奇怪的條件:所有數的最大公約數為 \(1\),也就是至少有一個奇數,這提示我們從奇偶數下手。
發現第二步中的最大公約數的奇數因子是毫無意義的,因為無論是奇數還是偶數除以一個奇數,奇偶性都不變,沒有改變第一步操作次數的奇偶性。
這給了先手一種必勝的思路,如果只進行第一步,先手必勝,先手又能保證兩人每一次第二步中的最大公約數為奇數就必勝。
先手只需要每一次隨便選一個偶數減 \(1\),由於初始至少有一個奇數,所以後手操作的時候至少有兩個奇數,最大公約數一定為奇數,先手的操作最大公約數就更顯然是奇數了。
這種情況的初始條件是隻進行第一步先手必勝,也就是偶數個數為奇數。
如果只進行第一步先手必敗呢?這時候先手肯定不能留給後手奇數,否則後手採用前面的方法必勝。所以先手只有一種選擇,第一步刪奇數。
如果初始奇數的個數大於 \(1\),那麼先手刪不完所有的奇數,後手必勝。
到現在,我們有三種判定了:
- 如果有 \(1\) 直接判定
- 如果有奇數個偶數先手必勝
- 如果有偶數個偶數並且有大於一個奇數後手必勝
如果恰好有偶數個偶數而且只有一個奇數,先手會刪那個奇數,直接模擬這一次操作將奇數減 \(1\),這時所有的數都為偶數,最小公因數最小為 \(2\),最多進行 \(log\) 次就會變成上面三種情況的一種。
單次模擬時間複雜度為 \(O(nloga)\),總時間複雜度為 \(O(nlog^{2}a)\)。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n;
int a[N];
int ji,ou,now=1,sum=0;
bool flag=false;
void change(){
for(int i=1;i<=n;i++){
if(a[i]&1) a[i]--;
}
int gcd=a[1];
for(int i=2;i<=n;i++) gcd=__gcd(gcd,a[i]);
for(int i=1;i<=n;i++) a[i]/=gcd;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]&1) ji++;
else ou++;
if(a[i]==1) flag=true;
sum+=(a[i]-1);
}
if(flag){
if(sum&1) cout<<"First";
else cout<<"Second";
return 0;
}
if(ou&1){
cout<<"First";
return 0;
}
else if(!(ou&1) && ji>1){
cout<<"Second";
return 0;
}
while(1){
now=3-now;
change();
ji=ou=0;
sum=0;
for(int i=1;i<=n;i++){
if(a[i]&1) ji++;
else ou++;
if(a[i]==1) flag=true;
sum+=(a[i]-1);
}
if(flag){
if(!(sum&1)) now=3-now;
break;
}
if(ou&1){
break;
}
else if(!(ou&1) && ji>1){
now=3-now;
break;
}
}
if(now==1) cout<<"First";
else cout<<"Second";
return 0;
}