文章
35
粉丝
599
获赞
6
访问
311.6k
#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;
}
登录后发布评论
暂无评论,来抢沙发