AT2305-[AGC010D]Decrementing【博弈论】
生活随笔
收集整理的這篇文章主要介紹了
AT2305-[AGC010D]Decrementing【博弈论】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/AT2305
題目大意
nnn個數字兩個人進行博弈,每個人的操作為
- 選擇一個大于1的數字減一
- 之后所有數字除以所有數字的gcdgcdgcd
無法操作者敗,保證初始所有數字互質
求是否先手必勝
1≤n≤1051\leq n\leq 10^51≤n≤105
解題思路
好妙的題目,先不考慮除gcdgcdgcd的話,那么就是考慮∑i=1n(ai?1)\sum_{i=1}^n(a_i-1)∑i=1n?(ai??1)的奇偶性。
假設目前為奇狀態,那么先手的目的顯然是要保持這個奇數狀態,注意到如果減去后除以的是一個奇數那么狀態顯然后手無法改變,所以只要保證序列中有奇數即可,因為如果要有偶數那么就可以減去這個偶數變成奇數先手顯然可以保持狀態不變。
如果目前為偶狀態,那么先手的目前就是要減去后任然是偶狀態,那么只有可能除以一個偶數,也就是要讓所有的數字都變成偶數。如果奇數個數大于111顯然不可行,否則減去這個111后進行一個子任務的博弈即可。
最多這樣logailog\ a_ilog?ai?次所以時間復雜度O(nlog?2ai)O(n\log^2 a_i)O(nlog2ai?)
code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10; int n,a[N]; int main() {scanf("%d",&n);bool k=1,one=0;int s=0,z=0;for(int i=1;i<=n;i++){scanf("%d",&a[i]);s+=a[i]-1;z+=(a[i]&1);one|=(a[i]==1);}while(1){if(s&1)return puts(k?"First":"Second")&0;if(one)return puts(k?"Second":"First")&0;if(z==1){for(int i=1;i<=n;i++)if(a[i]&1){a[i]--;break;}int d=0;z=one=s=0;for(int i=1;i<=n;i++)d=__gcd(a[i],d);for(int i=1;i<=n;i++){a[i]/=d;s+=a[i]-1;z+=(a[i]&1);one|=(a[i]==1);}k=!k;}else return puts(k?"Second":"First")&0;}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的AT2305-[AGC010D]Decrementing【博弈论】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年二建报名时间 报考2020年二
- 下一篇: P7515-[省选联考 2021A卷]矩