题意:要求长度为N的二进制数字中,它的所有字串(注意是any)中0 1的差的绝对值不大于K。
做法:从长度为1 的时候开始算起,每一次操作都是增加了一个1或者一个0,那么可以为用这个当做状态,记得状态划分时,增加末尾数字改变的是任何一个含有末尾字符的字串中0,1的数量,这里就有一个递推关系了,要当前状态的后缀字串有效,那么必须它的前面的那个字符够成的后缀字串有效,这样一来,最终会把所有字符串中的所有字串考虑进去。一开始是想考虑所有前缀串的,可是无法与状态结合起来啊。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#define LMT 65
#define LL long long
using namespace std;
LL dp[LMT][135][135],ans;
int k,n;
void init(void)
{
memset(dp,0,sizeof(dp));
ans=0;
}
inline int abs(int x)
{
return x>0?x:-x;
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
init();
dp[1][LMT+1][LMT-1]=dp[1][LMT-1][LMT+1]=1;
for(int i=1;i<n;i++)
for(int j=-i+LMT;j<=i+LMT;j++)
for(int t=-i+LMT;t<=i+LMT;t++)
{
int k1=j-LMT,k2=t-LMT,num;
if(abs(k1+1)<=k&&abs(k2-1)<=k)
{
num=(k1>=0?k1:0)+1;
dp[i+1][num+LMT][k2-1+LMT]+=dp[i][j][t];
}
if(abs(k1-1)<=k&&abs(k2+1)<=k)
{
num=(k2>=0?k2:0)+1;
dp[i+1][k1-1+LMT][num+LMT]+=dp[i][j][t];
}
}
for(int j=-n+LMT;j<=n+LMT;j++)
for(int t=-n+LMT;t<=n+LMT;t++)
ans+=dp[n][j][t];
printf("%lld\n",ans);
}
return 0;
}