洛谷P2490 [SDOI2011]黑白棋(K-NIM)
开始渐渐理解博弈
首先提出一个结论:在最优策略下,白棋只会向右走,黑棋只会向左走
证明 :
若白棋向左走,那黑棋可以向左走相同的步数,但此时白棋的活动范围减少,显然会劣,黑棋同理
接下来考虑模型转换
把每一对棋子之间的点数看做石子数,那本题就是经典的 k-NIM 博弈
不妨解释一下 K-NIM 博弈
K-NIM 博弈
定义:共有 \(n\) 堆石子,每次可以从任意不超过 \(k\) 堆石子中拿走任意石子
在某次无法操作时,该人失败,游戏结束
先手必败:
当且仅当把每堆石子的数量转换成二进制后,每个二进制位上的和 %(k+1) 后均等于零
先手必胜:
只要不满足上述情况,均为先手必胜局面
解释一下为什么膜 \((k+1)\)
考虑多余的部分,对于 \([0,k]\)
若对面正处于必败局面,在对面操作后,更改的范围一定为 \([0,k]\)
那次者则可操作对应的步数 \([k,0]\) 使其重返必败局面
所以要膜 \((k+1)\)
证明:
首先所有堆石子数量均为0的状态一定为必败局面,此时显然满足先手必败
如果存在堆石子数量不为0,但满足先手必败局面,在对面操作完后,次者一定可以操作对应的石子数量使其重返必败局面
假设在修改完其中一堆石子后二进制最高位不为0的位数为m,那一定可以拿走对应的石子数量使其最高位变为0
因此满足先手必败,反之同理
转移就很好写了
令 \(dp_{i,j}\) 表示二进制前 \(i\) 位膜完后均为 \(0\) ,此时共选了 \(j\) 个石子的方案数
枚举哪几堆添加石子,则:
\[dp_{i+1,j+(1<<i)*x*(k+1)}+=dp_{i,j}\binom{\frac{m}{2}}{x*(k+1)}
\]
因为每一对是无位置的,所以
\[ans+=dp_{maxi,j}\binom{n-i-\frac{m}{2}}{\frac{m}{2}}
\]
\[ans=\binom{n}{k}-ans
\]
Code
#include <bits/stdc++.h>
#define re register
#define int long long
#define pir make_pair
#define fr first
#define sc second
#define db double
using namespace std;
const int mol=1e9+7;
const int maxn=1e7+10;
inline int qpow(int a,int b) { int ans=1; while(b) { if(b&1) (ans*=a)%=mol; (a*=a)%=mol; b>>=1; } return ans; }
inline int read() {
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
int n,k,m,fac[10010],inv[10010];
inline int C(int n,int m) { if(n<m) return 0; return fac[n]*inv[m]%mol*inv[n-m]%mol; }
int f[22][100010];
signed main(void) {
freopen("erp.in","r",stdin); freopen("erp.out","w",stdout);
n=read(),k=read(),m=read();
fac[0]=1; for(re int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mol;
inv[n]=qpow(fac[n],mol-2); for(re int i=n;i>=1;i--) inv[i-1]=inv[i]*i%mol;
f[0][0]=1;
for(re int i=0;i<=20;i++)
for(re int j=0;j<=n;j++)
for(re int x=0;j+(1<<i)*x*(m+1)<=n-k&&x*(m+1)<=k/2;x++) {
(f[i+1][j+(1<<i)*x*(m+1)]+=f[i][j]*C(k/2,x*(m+1))%mol)%=mol;
}
int ans=0;
for(re int i=0;n-i-k/2>=0;i++) (ans+=f[21][i]*C(n-i-k/2,k/2)%mol)%=mol;
printf("%lld\n",(C(n,k)-ans+mol)%mol);
}