bzoj2281 [Sdoi2011]黑白棋
一眼$nimk$游戏,后来觉得不对劲,看了黄学长博客发现真的不是$nimk$。
就当是$nimk$做吧,那么我们要保证每一位上一的个数都是$d+1$的倍数。
$dp$:$f[i][j]$表示从低到高第$i$位,前i位用了$j$个石子,必败的方案数
最后一个挡板法统计答案即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 10050 7 #define mod 1000000007 8 #define int long long 9 using namespace std; 10 int C[N][108],bit[20],n,K,d; 11 int f[20][N],ans; 12 signed main(){ 13 scanf("%lld%lld%lld",&n,&K,&d); 14 bit[0]=1; 15 for(int i=1;i<=16;i++)bit[i]=bit[i-1]<<1; 16 for(int i=0;i<=10005;i++){ 17 C[i][0]=1; 18 for(int j=1;j<=min(i,105ll);j++) 19 C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; 20 } 21 f[0][0]=1; 22 for(int i=0;i<15;i++){ 23 for(int j=0;j<=n-K;j++){ 24 for(int k=0;k*(d+1)<=K/2&&j+k*(d+1)*bit[i]<=n-K;k++){ 25 (f[i+1][j+k*(d+1)*bit[i]]+=f[i][j]*C[K/2][k*(d+1)]%mod)%=mod; 26 } 27 } 28 } 29 ans=C[n][K]; 30 for(int i=0;i<=n-K;i++)ans=(ans-f[15][i]*C[n-i-K+K/2][K/2]%mod+mod)%mod; 31 printf("%lld\n",ans); 32 return 0; 33 }
人生如梦亦如幻 朝如晨露暮如霞。