2013 GDCPC J. Boring sequence

    题目不说了,大牛眼中的水题,我等水货想都想不到。。。

    直接贴代码,优化的面目全非。。。
    后来没有其他测试,只测试了题目中的几个样例以及1000 999之类的,不能保证代码完全正确,欢迎排错

/*
 * 定义 dp[i][j][0]为长度为i以j个0结尾的串的数量
 * 推出公式
 * dp[i][1][0]=sum(dp[i][k][1])(1<=k&&k<=K)
 * 优化过程为dp[i][j]=dp[i-1][j-1],即直接加一个与串末相同字符即可
 * 计算2的阶乘和计算和时,使用模运算
 * 因为dp[i][j][0]==dp[i][j][1],只有dp[i][1]有用
 * 继续优化空间
 * 发现最终的ans和dp[n+1]是一样的求法,故终极优化
 */
#include <iostream>
using namespace std;

const int MOD=1007;
const int maxn=1002;
int dp[maxn]={2,2};
int b[maxn]={0,1};

int main()
{
//  freopen("in.txt","r",stdin);
    for(int i=2;i<maxn;i++)
        b[i]=(b[i-1]*2) % MOD;

    int n,K;
    while(~scanf("%d%d",&n,&K))
    {
        n++;
        for(int i=2;i<=n;i++)
        {
            dp[i]=0;
            for(int k=1;k<=i-1&&k<=K;k++)
                dp[i]=(dp[i]+dp[i-k])%MOD;
        }
        printf("%d\n",(b[n]-dp[n]+MOD)%MOD);
    }
}

     由优化的代码产生的具象的想法:定义d[i]为连续相同字符长度不超过K的01字符串的个数,则d[i]可分为:

     d[i-1]:最后字符若为0,则添加1个1,反之为1,添加1个0。

     d[i-2]:最后字符若为0,则添加2个1,反之为1,添加2个0。

     ...

     d[i-k]:最后字符若为0,则添加k个1,反之为1,添加k个0。

     即 d[i] = sum(d[j])( max(1, i-k) <= j <= i-1)

     01串的题基本都是从最后开始递推,累加。优化方式有快速幂等。

     看了一下和以前做的杭电2604挺像,之前写的解题报告:http://www.cnblogs.com/IT-BOY/archive/2013/02/03/2890841.html

posted @ 2013-05-13 20:41  SF-_-  阅读(465)  评论(0编辑  收藏  举报