文章

35

粉丝

599

获赞

6

访问

309.8k

头像
这题应该是动归啊 附带一个镜像题
P1726 中山大学2019年机试题
发布于2020年5月10日 09:37
阅读数 8.4k

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int dp[35];
int main()
{
//	若i < m,第i位不管是0还是1都不可能有m个连续1的情况出现,因此此时dp[i] = dp[i-1] * 2 
//	2.若i == m,第i位若为1,会和向前回溯m-1位都是1的情况,合并成一个长度为m的连续1串;第i位若为0,则不会构成这种连续的情况。因此此时dp[i] = dp[i-1] * 2 - 1 
//	3.若i > m,此时若i为1,且向前回溯m-1位都是1,会合并构成一个长度为m的连续1串(类似情况2),此时需要做的是在总情况数里减去这种连续的情况,那么怎么知道这种连续的情况是多少呢?其实答案就是dp[i-m-1],意味着由前面的从第一位开始到第i-m-1位的合法情况加上连续的m位为1的情况,构成了这样的一个非法串。 
//	最后不要忘记了我们是逆向求解的,因此2^n - dp[n]才为所求。
	
	int n,m;
	while (~scanf("%d %d", &n, &m))
	{
		if (n == -1 && m == -1) break;
		dp[0] = 1;
		for (int i = 1; i <= n; i++)
		{
			if (i < m) dp[i] = 2 * dp[i-1];
			else if (i == m) dp[i] = 2 * dp[i-1] - 1;
			else dp[i] = 2 * dp[i-1] - dp[i-m-1];
		}
		printf("%d\n",(int)pow(2,n) - dp[n]);
	}
	return 0;
}

 

登录查看完整内容


登录后发布评论

暂无评论,来抢沙发