zoj 3747 Attack on Titans 递推 计数dp

来源:互联网 发布:知乎周刊plus epub 编辑:程序博客网 时间:2024/06/03 04:54

题意:给定三种士兵G,R,P,有无限个,要求取出一个排列为n人,要求满足至少m个连续个G士兵,至多k个连续的R士兵,P士兵不作要求。求排列总数,对1000000007取模。
思路:http://blog.csdn.net/cc_again/article/details/10858813。不是很懂取模什么意思

#include<cstdio>#include<cstdlib>#include<time.h>#define ll long longconst int maxn = 1000000+10;//至少m个G   至多k个R   p任意 const int mod=1000000007;ll dp[maxn][3];//[0]表示第i个为G,[1]表示R  [2] 表示p int n,m,k;int solve(int u,int r)//代表G至多u个,   R至多r个 {for(int i=1;i<=n;i++){ll sum= (dp[i-1][0]+dp[i-1][1]+dp[i-1][2])%mod;//中间结果用ll存,否则溢出 dp[i][2]=sum;if(i<=u)dp[i][0]=sum;else if(i==u+1)dp[i][0]=(sum-1)%mod;else if(i>u+1)dp[i][0]=(sum-dp[i-u-1][1]-dp[i-u-1][2])%mod;if(i<=r)dp[i][1]=sum;else if(i==r+1)dp[i][1]=(sum-1)%mod;else if(i>r+1)dp[i][1]=(sum-dp[i-r-1][0]-dp[i-r-1][2])%mod;}return (dp[n][0]+dp[n][1]+dp[n][2])%mod;}int main(){//freopen("in.txt","r",stdin);while(scanf("%d%d%d",&n,&m,&k)!=EOF){dp[0][0]=1;dp[0][1]=dp[0][2]=0;int ans=((solve(n,k)-solve(m-1,k))%mod+mod)%mod;printf("%d\n",ans);}}

原创粉丝点击