题解 P2490【[SDOI2011]黑白棋】
思路
搞了好久终于搞懂了...
前置知识:k-\text{Nim} 游戏
描述
有
解法
记数
先写出结论:若
证明
有向无环图博弈满足一下几点:
- 终止状态为
\text{P} 态
所有堆都为
- 所有的
\text{N} 态只能转移至\text{P} 态
对于一次操作,必定会取走一些棋子,使得某一位上的数值发生改变,改变的范围只有
- 所有的
\text{P} 态都有至少一种方案转移至\text{N} 态
记
证毕。
回到本题,我们发现棋子不能跨越另外一颗棋子,则最后
考虑一个
考虑在新的一位中选出
方案即
其中
注意要记得转换回原方案。
时间复杂度
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int mod=1e9+7,N=1e4+10;
int n,k,d,dp[14][N];
int C[N][205];
inline void init(){
C[0][0]=1;
for(int i=1;i<=n;i++){
C[i][0]=1;
for(int j=1;j<=min(i,k);j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
int main(){
n=read(),k=read(),d=read();
init();
dp[0][0]=1;
for(int i=0,p=1;i<=12;i++,p<<=1)
for(int j=0;j<=n-k;j++)
for(int x=0;j+p*x*(d+1)<=n-k&&x*(d+1)<=k/2;x++)
dp[i+1][j+p*x*(d+1)]=(dp[i+1][j+p*x*(d+1)]+1ll*dp[i][j]*C[k/2][x*(d+1)])%mod;
int ans=0;
for(int i=0;i<=n-k;i++)
ans=(ans+1ll*dp[13][i]*C[n-i-k/2][k/2])%mod;
printf("%d",(C[n][k]+mod-ans)%mod);
flush();
return 0;
}
再见 qwq~