AtCoder 2305 [AGC010D] Decrementing(博弈)
problem
Luogu鏈接
solution
case1:aaa 中如果有 111 的存在,那么相當(dāng)于第二步失效,最后的結(jié)果僅由 ∑ai?1\sum a_i-1∑ai??1 的奇偶性決定(奇數(shù)先手贏,偶數(shù)后手贏)
奇數(shù)先手贏,偶數(shù)后手贏。
case2:如果 ∑ai?1\sum a_i-1∑ai??1 為奇數(shù),先手必勝。
這看起來(lái)就似乎是正確的。
首先因?yàn)榕紨?shù)除以奇數(shù)還是偶數(shù),奇數(shù)除以奇數(shù)還是奇數(shù),所以如果 gcd?\gcdgcd 是奇數(shù),對(duì)奇偶性不影響。
如果先手能維持這個(gè)奇偶性到最后,即保證每人每次只有第一步操作有效,那他就贏了。
先手只需任選一個(gè)偶數(shù) ?1-1?1,再算上初始局面必然包含的一個(gè)奇數(shù)(否則初始 gcd?\gcdgcd 不為 111),這樣至少就有兩個(gè)奇數(shù)。
- 此時(shí)若序列長(zhǎng)度 >2>2>2,先手 ?1-1?1 之后:
- gcd?=1\gcd=1gcd=1。后手再讓任意一個(gè)數(shù) ?1-1?1,序列的 gcd?\gcdgcd 仍然為 111,后手的第二步等價(jià)于無(wú)效。
- gcd?≠1\gcd\ne 1gcd?=1,但 gcd?\gcdgcd 也一定是奇數(shù)。除掉 gcd?\gcdgcd 后,出現(xiàn) 111,奇偶性未改變。后手仍然面臨的奇偶性為偶。先手必勝。
- 特殊情況是序列長(zhǎng)度 =2=2=2,先手 ?1-1?1 之后:
- 可能兩數(shù)相等,那正好就直接贏了。
- 要是不相等,并且 ?1-1?1 之后出現(xiàn)了倍數(shù)關(guān)系,那沒(méi)什么影響,顯然一個(gè)是另一個(gè)的奇數(shù)倍。約去 gcd?\gcdgcd 后就是一個(gè) 111 加上一個(gè)奇數(shù),后手面臨的奇偶性仍然為偶,先手仍然獲勝。
要想保證每人每次只能取一個(gè)也很簡(jiǎn)單,先手只需任選一個(gè)偶數(shù)減1,再算上初始局面必然包含的一個(gè)奇數(shù)(否則初始gcd不為1),這樣就至少有兩個(gè)奇數(shù)了。
case3:如果 ∑i=1nai?1\sum_{i=1}^na_i-1∑i=1n?ai??1 為偶數(shù),且有 >1>1>1 個(gè) aia_iai? 為奇數(shù),則先手必?cái) ?/p>
若有多個(gè)奇數(shù),這一輪先手選擇一個(gè)變?yōu)榕紨?shù),gcd?\gcdgcd 仍然只可能是奇數(shù),下一輪后手就能將其重新變回偶數(shù),使先手第二步無(wú)效。
case4:如果為偶數(shù),先手肯定想要翻盤,唯一辦法是 2∣gcd?2\mid \gcd2∣gcd。
如果 ∑i=1nai?1\sum_{i=1}^na_i-1∑i=1n?ai??1 為偶數(shù),且只有一個(gè)奇數(shù),先手一定操作這個(gè)奇數(shù),那么這一輪至少能 /2/2/2,這是唯一的翻盤機(jī)會(huì)。
考慮做完上述特判和操作后,將操作權(quán)遞交給對(duì)手。
只有 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; }總結(jié)
以上是生活随笔為你收集整理的AtCoder 2305 [AGC010D] Decrementing(博弈)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 修改病句大方法修改病句大方法的例子
- 下一篇: 一般图带权多重匹配(欧拉图+最小费用流)