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); } }