首页 > 其他分享 >[AGC010D] Decrementing

[AGC010D] Decrementing

时间:2024-10-21 11:34:14浏览次数:1  
标签:先手 AGC010D 必胜 int 奇数 偶数 Decrementing 最大公约数

首先考虑最简单的情况,如果有一个数是 \(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;
}

标签:先手,AGC010D,必胜,int,奇数,偶数,Decrementing,最大公约数
From: https://www.cnblogs.com/wangwenhan/p/18489109

相关文章