[??记录]AT2305 [AGC010D] Decrementing

command_block

2021-03-15 22:07:14

Personal

**题意** :给出 $n$ 个整数。第 $i$ 个整数是 $A_i$ ,它们的最大公约数为 $1$ 。 A 和 B 进行博弈。A 为先手,他们将轮流进行以下操作(以下两步相当于一次操作): - 选择黑板中大于 $1$ 的一个数,将其减 $1$。 - 此后,将黑板上所有数全部除以所有数的最大公约数。 不能再进行操作的人失败。两人都选择最好的方式行动,请求出谁会最终胜利。 $n\leq 10^5,a_i\leq 10^9$ ,时限$\texttt{2s}$。 ------------ 加减法和 $\rm gcd$ 搞一块,有点神必,应该不至于是大型性质题。先莽一些特殊情况。 不难发现,若数字中存在 $1$ ,那么公因数总是 $1$ ,操作的第二部就无影响了。 接下来就是两人轮流给所有数减一,若有奇数个偶数,先手必胜,否则必败。 我们发现“减一”这个操作不能跨越奇偶性,于是顺着这个思路继续扩展。 - 若有奇数个偶数,则先手必胜。(由于开始时互质,必然至少有一个奇数) 具体方法 : 归纳证明。先手面对有奇数个偶数,且至少有一个奇数的局面。 先手操作一个偶数,使其变为奇数,若仍存在偶数,公因数仍然为 $1$,否则公因数可能不为 $1$ ,但所引发的操作不会影响偶数个数(因为本来就没有偶数了)。 此时后手有偶数个偶数,和至少两个奇数。无论如何操作,都会产生奇数个偶数,且公因数必定为 $1$。 而终止态没有偶数,游戏一定会结束,故后手一定会得到终止态,后手必败。 - 若有偶数个偶数,且有**大于一个**奇数,后手必胜。 先手无论如何操作,都只会把“有奇数个偶数,且至少有一个奇数”的必胜局面送给后手。 此外,若只有一个奇数,先手只能操作这个奇数(否则必败),然后使得所有数除以 $\gcd$。若该数已经为 $1$ ,先手必败。 不可能没有奇数。 这最多持续 $O(\log a)$ 次,于是复杂度为 $O(n\log a)$。 ```cpp #include<algorithm> #include<cstdio> #define MaxN 100500 using namespace std; int gcd(int a,int b) {return !b ? a : gcd(b,a%b);} bool solve(int *a,int n) { int c0=0,c1=0; for (int i=1;i<=n;i++) if (a[i]&1)c1++; else c0++; if (c0&1)return 1; if (!(c0&1)&&c1>2)return 0; for (int i=1;i<=n;i++) if (a[i]&1) if (a[i]>1)a[i]--; else return 0; int d=0; for (int i=1;i<=n;i++)d=gcd(a[i],d); for (int i=1;i<=n;i++)a[i]/=d; return !solve(a,n); } int n,a[MaxN]; int main() { scanf("%d",&n); for (int i=1;i<=n;i++)scanf("%d",&a[i]); puts(solve(a,n) ? "First" : "Second"); return 0; } ```