zoj3747(递推dp)

 

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5170

题意:给n个士兵排队,每个士兵三种G、R、P可选,求至少有m个连续G士兵,最多有k个连续R士兵的排列的种数。

 

详细解法:http://blog.csdn.net/cc_again/article/details/24841249

注意下取模后为负的情况

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 1000010
#define clr(a) (memset(a,0,sizeof(a)))
using namespace std;
LL dp[N][3];
LL m,n,k;
LL solve(LL u,LL v)
{
    dp[0][0]=1;dp[0][1]=0;dp[0][2]=0;
    for(int i=1;i<=n;i++)
    {
        LL sum=(dp[i-1][0]+dp[i-1][1]+dp[i-1][2])%mod;
        dp[i][2]=sum;
        if(i<=u)dp[i][0]=sum;
        else if(i==u+1)dp[i][0]=sum-1;
        else dp[i][0]=(sum-dp[i-u-1][1]-dp[i-u-1][2]+mod)%mod;
        if(i<=v)dp[i][1]=sum;
        else if(i==v+1)dp[i][1]=sum-1;
        else dp[i][1]=(sum-dp[i-v-1][0]-dp[i-v-1][2]+mod)%mod;
    }
    return (dp[n][0]+dp[n][1]+dp[n][2])%mod;
}
int main()
{
    while(scanf("%lld%lld%lld",&n,&m,&k)>0)
    {
        printf("%lld\n",((solve(k,n)-solve(k,m-1))%mod+mod)%mod);
    }
}
View Code

 

posted on 2015-01-02 20:10  lienus  阅读(532)  评论(0编辑  收藏  举报

导航