[agc010D]Decrementing-[。。。思考题]

Description

传送门

Solution

 真是够神秘的啊。。。

Alice和Bob两个真的城会玩。

不过本题一个暗示挺明显的。就是黑板上所有数不论何时gcd为1。

考场上我以为会很复杂,结果。。是我想多了qaq,人家就是用来判断奇偶性的。

由于gcd为1,黑板上必定有一个数为奇数。

假如n个数中偶数的个数为奇数,则先手必胜。

先手可以将一个偶数变成奇数,然后后手做什么,就做对应的策略。(后手奇->偶,先手就偶->奇;后手偶->奇,先手还偶->奇)。

因为我们保证在后手操作的时候偶数个数一定是偶数(好绕的说),所以不论什么时候先手都有对应的策略(如果后手动了偶数,肯定还有一个偶数给先手操作呢)。然后1是奇数,所以最后动不下去的肯定是后手啦。

然后,假如黑板上偶数的个数为偶数,并且奇数的个数>1,则先手不管怎么动都会使得偶数个数为奇数,然后。。后手就稳赢了(参考上文)

那如果奇数的个数为1呢?如果这个奇数本身就为1,先手肯定动不了它,那情况同上;如果奇数本身不为1,那就递归求解吧哈哈哈。。(反正也也递归不了多少次,每次所有数最少/2呢)

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int n,a[100010],cnt=0,id;
int gcd(int a,int b){if (!b) return a;return gcd(b,a%b);}
bool dfs()
{
    id=-1;cnt=0;
    for (int i=1;i<=n;i++) if (!(a[i]&1)) cnt++;else if (a[i]!=1) id=i;
    if (cnt&1) return 1;
    if (cnt!=n-1||(cnt==n-1&&id==-1)) return 0;
    a[id]--;int g=a[id];
    for (int i=1;i<=n;i++) g=gcd(g,a[i]);
    for (int i=1;i<=n;i++) a[i]/=g;
    return !dfs();
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    printf("%s",dfs()?"First":"Second");
}
原文地址:https://www.cnblogs.com/coco-night/p/9629998.html