题目
思路
根据黑白棋的距离做一个k-nim然后dp,dp方程见代码(那么长的方程要命啊)
code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
long long c[10004][104],f[20][10004],n,k,d;
const long long mod=1e9+7;
long long ans;
inline long long read()
{
long long p=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
p=(p<<3)+(p<<1)+c-'0';
c=getchar();
}
return f*p;
}
int main()
{
n=read(),k=read(),d=read();
c[0][0]=1;
for (long long i=1;i<=n;i++)
{
c[i][0]=1;
for (long long j=1;j<=k;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
f[0][0]=1;
for (long long i=0;i<=18;i++)
{
for (long long j=0;j<=n-k;j++)
{
for (long long l=0;l*(d+1)<=k/2&&(1ll<<i)*l*(d+1)+j<=n-k;l++)
{
f[i+1][j+(1ll<<i)*l*(d+1)]=(f[i+1][j+(1ll<<i)*l*(d+1)]+1ll*f[i][j]*c[k/2][l*(d+1)]%mod)%mod;
}
}
}
for (long long i=0;i<=n-k;i++) ans=(ans+1ll*f[19][i]*c[n-i-k/2][k/2])%mod;
cout<<(c[n][k]-ans+mod)%mod;
return 0;
}