对弈(nim-k游戏博弈)
problem
AliceAliceAlice 和 BobBobBob 又在玩游戲。
AliceAliceAlice 和 BobBobBob 在一個(gè) 1×n1\times n1×n 的網(wǎng)格圖上玩游戲,網(wǎng)格圖的 nnn 個(gè)格子中,有 kkk 個(gè)格子內(nèi)被各放了一個(gè)棋子,其中 kkk 是一個(gè)偶數(shù)。
從左到右,這 kkk 個(gè)棋子依次被染色為紅色、藍(lán)色、紅色、……、藍(lán)色、紅色、藍(lán)色。其中紅棋子是 AliceAliceAlice 的,藍(lán)棋子是 BobBobBob 的。
兩人輪流操作,需要遵循以下規(guī)則:
-
每一回合輪到某人操作時(shí),這個(gè)人只能移動(dòng)自己的棋子。
-
每個(gè)棋子只能在網(wǎng)格圖內(nèi)的格子之間移動(dòng),并且在移動(dòng)棋子的時(shí)候,每個(gè)棋子不能跨過和這個(gè)棋子相鄰的其它棋子。
-
每次最少需要移動(dòng) 111 個(gè)棋子,最多可以移動(dòng) mmm 個(gè)棋子。
-
若移動(dòng)多個(gè)棋子,則必須選擇多個(gè)不同的棋子分別移動(dòng),每一個(gè)被選擇移動(dòng)的棋子不能停留在原位。
例如下圖,當(dāng) AliceAliceAlice 操作時(shí),若她要移動(dòng)從左到右的第三個(gè)紅棋子,那么她可以移動(dòng)到的范圍有下面這三個(gè)空心棋子的位置。
若某一回合,輪到某人操作時(shí),這個(gè)人無法操作,那么這個(gè)人就輸了。
現(xiàn)在 先手,假設(shè)兩人均采用最優(yōu)策略。
給定 n,k,mn,k,mn,k,m,請(qǐng)你求出有多少符合題意的初始局面,使得 AliceAliceAlice 必勝。對(duì) 1e9+71e9+71e9+7 取模。
solution
observation:BobBobBob 只會(huì)向左移動(dòng),AliceAliceAlice 只會(huì)向右移動(dòng)。
證明:因?yàn)槿绻?BobBobBob 向右移動(dòng),那么其左邊的 AliceAliceAlice 的格子就會(huì)跟著移動(dòng)【一直擠 BobBobBob 】,相互擠對(duì)方,但左邊第一個(gè)是屬于 AliceAliceAlice 的格子,所以最后一定是 AliceAliceAlice 會(huì)擠著 BobBobBob。AliceAliceAlice 向左移動(dòng)也是同理。
所以把一個(gè) AliceAliceAlice 和一個(gè) BobBobBob 的格子綁成一對(duì)。
記 ai:a_i:ai?: 第 iii 個(gè)紅棋的位置,bi:b_i:bi?: 第 iii 個(gè)藍(lán)棋的位置,di=bi?ai?1d_i=b_i-a_i-1di?=bi??ai??1。
這相當(dāng)于有 k2\frac{k}{2}2k? 堆石子,每堆石子個(gè)數(shù)為 did_idi?。
這就轉(zhuǎn)化成了經(jīng)典的 nim-k 游戲【每次可以選擇 1~k1\sim k1~k 堆石子,拿走任意的石子數(shù)量,最后不能操作者輸。】
結(jié)論:當(dāng)所有的 did_idi? 轉(zhuǎn)化成二進(jìn)制后,每個(gè)二進(jìn)制位上為 111 的個(gè)數(shù) %(k+1)=0\%(k+1)=0%(k+1)=0 則是必?cái)【置妗?/p>
證明:
-
全 000 的局面一定是 PPP 局面。
-
任何一個(gè) PPP 狀態(tài),經(jīng)過一次操作以后必然會(huì)到達(dá) NNN 狀態(tài)。
-
在某一次移動(dòng)中,至少有一堆被改變,即至少有一個(gè)二進(jìn)制位被改變。
由于最多只能改變 kkk 堆石子,所以對(duì)于任何一個(gè)二進(jìn)制位,111 的個(gè)數(shù)至多改變 kkk。
又有原先總數(shù)為 k+1k+1k+1 的整數(shù)倍,所以改變之后必然不可能仍是 k+1k+1k+1 的整數(shù)倍。
故在 PPP 狀態(tài)下一次操作的結(jié)果必然是 NNN 狀態(tài)。
-
-
任何 NNN 狀態(tài),總有一種操作使其變化成 PPP 狀態(tài)。
-
從高位到低位考慮所有的二進(jìn)制位。
假設(shè)用了某種方法,改變了 mmm 堆,使 iii 位之前的所有位都變?yōu)?k+1k+1k+1 的整數(shù)倍。
現(xiàn)在要證明總有一種方法讓第 iii 位也恢復(fù)到 k+1k+1k+1 的整數(shù)倍(包括 000)。
顯然,對(duì)于那些已經(jīng)改變的 mmm 堆,當(dāng)前的第 iii 位可以自由選擇 111 或000【這只取決于操作時(shí)后拿走的石子個(gè)數(shù)】。
不考慮已經(jīng)操作的 mmm 堆,記剩下的堆的第 iii 位上 111 的總和為 sumsumsum
-
分類討論:
-
sum≤k?msum\le k-msum≤k?m
此時(shí)可以將這些堆上的 111 全部拿掉,然后讓那 mmm 堆得 iii 位全部置成 000。
-
sum>k?msum>k-msum>k?m
此時(shí)我們?cè)谥案淖兊?mmm 堆中選擇 k+1?sumk+1-sumk+1?sum 堆,將他們的第 iii 位設(shè)置成 111。剩下的設(shè)置成000。
由于 k+1?sum<k+1?(k?m)<m+1?k+1?sum≤mk+1-sum<k+1-(k-m)<m+1\Rightarrow k+1-sum\le mk+1?sum<k+1?(k?m)<m+1?k+1?sum≤m,的確可以做到。
-
-
-
原博客證明
這樣就可以 dpdpdp 了,用所有方案減去必?cái)》桨浮?/p>
dpi,j:dp_{i,j}:dpi,j?: 考慮到二進(jìn)制位的 iii 位,一共用了 jjj 個(gè)石子的不合法方案數(shù)。
枚舉下一個(gè)二進(jìn)制有多少堆石子為 111,石子堆數(shù)必須是 m+1m+1m+1 的倍數(shù)。
dpi,j→dpi+1,j+2i+1?tdp_{i,j}\rightarrow dp_{i+1,j+2^{i+1}·t}dpi,j?→dpi+1,j+2i+1?t?
當(dāng)然需要考慮是哪幾堆,所以需要組合數(shù)。
最后要考慮將所有格子分成 kkk 堆,用隔板法計(jì)算。
code
#include <bits/stdc++.h> using namespace std; #define maxn 10005 #define int long long #define mod 1000000007 int fac[maxn], inv[maxn], dp[maxn]; int n, k, m;int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }void init() {fac[0] = inv[0] = 1;for( int i = 1;i <= n;i ++ ) fac[i] = fac[i - 1] * i % mod;inv[n] = qkpow( fac[n], mod - 2 );for( int i = n - 1;i;i -- ) inv[i] = inv[i + 1] * ( i + 1 ) % mod; }int C( int n, int m ) { return fac[n] * inv[m] % mod * inv[n - m] % mod; }signed main() {freopen( "chess.in", "r", stdin );freopen( "chess.out", "w", stdout );scanf( "%lld %lld %lld", &n, &k, &m );init();int ans = C( n, k );n -= k, k >>= 1;dp[0] = 1;for( int w = 0;w < 15;w ++ )for( int i = n;i;i -- )for( int j = m + 1;( 1 << w ) * j <= i and j <= k;j += m + 1 )dp[i] = ( dp[i] + dp[i - ( 1 << w ) * j] * C( k, j ) ) % mod;for( int i = 0;i <= n;i ++ )ans = ( ans - dp[i] * C( n - i + k, k ) % mod + mod ) % mod;printf( "%lld\n", ans );return 0; }總結(jié)
以上是生活随笔為你收集整理的对弈(nim-k游戏博弈)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么查自己的银行卡号 查询银行卡号的方法
- 下一篇: 【无码专区7】括号序列(思维)