日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AtCoder 2305 [AGC010D] Decrementing(博弈)

發布時間:2023/12/3 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AtCoder 2305 [AGC010D] Decrementing(博弈) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

problem

Luogu鏈接

solution

case1:aaa 中如果有 111 的存在,那么相當于第二步失效,最后的結果僅由 ∑ai?1\sum a_i-1ai??1 的奇偶性決定(奇數先手贏,偶數后手贏)

奇數先手贏,偶數后手贏。

case2:如果 ∑ai?1\sum a_i-1ai??1 為奇數,先手必勝。

這看起來就似乎是正確的。

首先因為偶數除以奇數還是偶數,奇數除以奇數還是奇數,所以如果 gcd?\gcdgcd 是奇數,對奇偶性不影響。

如果先手能維持這個奇偶性到最后,即保證每人每次只有第一步操作有效,那他就贏了。

先手只需任選一個偶數 ?1-1?1,再算上初始局面必然包含的一個奇數(否則初始 gcd?\gcdgcd 不為 111),這樣至少就有兩個奇數。

  • 此時若序列長度 >2>2>2,先手 ?1-1?1 之后:
    • gcd?=1\gcd=1gcd=1。后手再讓任意一個數 ?1-1?1,序列的 gcd?\gcdgcd 仍然為 111,后手的第二步等價于無效。
    • gcd?≠1\gcd\ne 1gcd?=1,但 gcd?\gcdgcd 也一定是奇數。除掉 gcd?\gcdgcd 后,出現 111,奇偶性未改變。后手仍然面臨的奇偶性為偶。先手必勝。
  • 特殊情況是序列長度 =2=2=2,先手 ?1-1?1 之后:
    • 可能兩數相等,那正好就直接贏了。
    • 要是不相等,并且 ?1-1?1 之后出現了倍數關系,那沒什么影響,顯然一個是另一個的奇數倍。約去 gcd?\gcdgcd 后就是一個 111 加上一個奇數,后手面臨的奇偶性仍然為偶,先手仍然獲勝。

要想保證每人每次只能取一個也很簡單,先手只需任選一個偶數減1,再算上初始局面必然包含的一個奇數(否則初始gcd不為1),這樣就至少有兩個奇數了。

case3:如果 ∑i=1nai?1\sum_{i=1}^na_i-1i=1n?ai??1 為偶數,且有 >1>1>1aia_iai? 為奇數,則先手必敗。

若有多個奇數,這一輪先手選擇一個變為偶數,gcd?\gcdgcd 仍然只可能是奇數,下一輪后手就能將其重新變回偶數,使先手第二步無效。

case4:如果為偶數,先手肯定想要翻盤,唯一辦法是 2∣gcd?2\mid \gcd2gcd。

如果 ∑i=1nai?1\sum_{i=1}^na_i-1i=1n?ai??1 為偶數,且只有一個奇數,先手一定操作這個奇數,那么這一輪至少能 /2/2/2,這是唯一的翻盤機會。

考慮做完上述特判和操作后,將操作權遞交給對手。

只有 case4 是需要模擬操作下去的 O(nlog?2w)O(n\log^2w)O(nlog2w),其余三種情況一步判斷輸贏即可。

#include <bits/stdc++.h> using namespace std; #define maxn 100005 #define int long long int n; int a[maxn];int gcd( int x, int y ) {if( ! y ) return x;else return gcd( y, x % y ); }signed main() {scanf( "%lld", &n );for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] );bool op = 0;while( 1 ) {int cnt = 0, sum = 0, flag = 0;for( int i = 1;i <= n;i ++ )cnt += (a[i] & 1), sum += a[i] - 1, flag |= (a[i] == 1);if( sum & 1 ) break;if( cnt ^ 1 ) { op ^= 1; break; }if( flag ) { op ^= 1; break; }int d = 0;for( int i = 1;i <= n;i ++ ) {if( a[i] & 1 ) a[i] --;d = gcd( d, a[i] );}for( int i = 1;i <= n;i ++ ) a[i] /= d;op ^= 1;}if( ! op ) puts("First");else puts("Second");return 0; }

總結

以上是生活随笔為你收集整理的AtCoder 2305 [AGC010D] Decrementing(博弈)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。