[AGC010D] Decrementing
首先考虑最简单的情况,如果有一个数是
然后发现题目给了一个很奇怪的条件:所有数的最大公约数为
发现第二步中的最大公约数的奇数因子是毫无意义的,因为无论是奇数还是偶数除以一个奇数,奇偶性都不变,没有改变第一步操作次数的奇偶性。
这给了先手一种必胜的思路,如果只进行第一步,先手必胜,先手又能保证两人每一次第二步中的最大公约数为奇数就必胜。
先手只需要每一次随便选一个偶数减
这种情况的初始条件是只进行第一步先手必胜,也就是偶数个数为奇数。
如果只进行第一步先手必败呢?这时候先手肯定不能留给后手奇数,否则后手采用前面的方法必胜。所以先手只有一种选择,第一步删奇数。
如果初始奇数的个数大于
到现在,我们有三种判定了:
- 如果有
直接判定 - 如果有奇数个偶数先手必胜
- 如果有偶数个偶数并且有大于一个奇数后手必胜
如果恰好有偶数个偶数而且只有一个奇数,先手会删那个奇数,直接模拟这一次操作将奇数减
单次模拟时间复杂度为
#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;
}
在那高远的黑色穹顶之下,它的牺牲使圣巢永世不衰
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步