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

 

你可能感兴趣的:(ZOJ)