首页 > 代码库 > zoj3747(递推dp)

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

 

zoj3747(递推dp)