1545 01-K Code

/*
d[n][i][j] 表示字符长度为n时,范围在i到j之间的字符串个数。
范围的计算:范围就是从第n个字符开始往前推1比0多的个数,i代表最小值,j代表最大值;
因为下标不能是负数所以处理的时候用5来表示0; 
比如 01011的范围就是0到2;
刚开始范围是 0到0 
1 的范围是0到1
11 的范围是0到2
011 的范围是0到2
1011 的范围是0到2
01011 的范围是0到2
先把k位的字符串预处理,然后就是递推了。 
递推的时候就是在前一个字符串后面加1或0;
d[n+1][i-1][j-1]+=d[n][i][j];
d[n+1][i+1][j+1]+=d[n][i][j]; 
边界要特殊处理一下详情看代码吧; 
*/
#include <stdio.h>
#include <string.h>
__int64 max(__int64 a,__int64 b)
{
	if(a>b) return a;
	else return b;
}
__int64 min(__int64 a,__int64 b)
{
	if(a<b) return a;
	else return b;
}
__int64 d[70][20][20],n,k;
void dp()
{
	__int64 mi,ma,l;
	for(int i=0;i<(1<<k);i++)
	{
		mi=ma=l=5;
		for(int j=1;j<(1<<k);j*=2)
		{
			if(i&j) l++;
			else l--;
			ma=max(ma,l);
			mi=min(mi,l);
		}
		d[k][mi][ma]++;
	}
	for(int i=k;i<n;i++)
	{
		d[i+1][6-k][6]+=d[i][5-k][5];	//d[i][5-k][5]后面只能加1,加0的话下界就是4-k
						//也就是-(k+1)因为题目要求-k到k所以-(k+1)就没必要算了 
		d[i+1][4][4+k]+=d[i][5][5+k];
		for(int j=6-k;j<=5;j++)
		for(int l=5;l<=4+k;l++)
		{
			d[i+1][min(j+1,5)][l+1]+=d[i][j][l];
			d[i+1][j-1][max(l-1,5)]+=d[i][j][l];
		}
	}
}
int main()
{
	__int64 sum;
	while(scanf("%I64d%I64d",&n,&k)!=-1)
	{
		if(n<=k) k=n;
		memset(d,0,sizeof(d));
		dp();
		sum=0;
		for(int i=5-k;i<=5;i++)
		for(int j=5;j<=5+k;j++)
		sum+=d[n][i][j];
		printf("%I64d\n",sum);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值