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

你可能感兴趣的:(sequence)