题意:
给n个士兵排队,每个士兵三种G、R、P可选,求至少有m个连续G士兵,最多有k个连续R士兵的排列的种数。
分析:
至多的情况比较好考虑,至少的情况比较复杂。
所以先把问题都转化成至多连续的情况:
设 表示至多 x 个连续的 y
即答案变为:
表示第i个为G,至多有u个连续G,至多有v个连续R的个数 //这里的u和v固定
表示第i个为R,至多有u个连续G,至多有v个连续R的个数 //这里的u和v固定
表示第i个为P,至多有u个连续G,至多有v个连续R的个数 //这里的u和v固定
当第i个为P时:
情况很好考虑不会对连续的R和G产生影响,
当第i个为G时
如果时 ,无论怎么放都不会超过u个连续的G这个限制条件 所以
如果时,要排除前u个都放了G的情况,
如果时,要排除从i-1到i-u位置都放了G的情况,
(因为这样保证了1位置上是G,所以区间不会出现连续的G)
当第i个为R时
如果 时 ,无论怎么放都不会超过v个连续的R这个限制条件 所以
如果时,要排除前v个都放了R的情况,
如果时,要排除从i-1到i-v位置都放了R的情况,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const ll mod=1000000007;
ll dp[maxn][3];
int u,v;
int n,m,k;
ll solve(){
for(int i=1;i<=n;i++){
if(i==1) dp[i][0]=dp[i][1]=dp[i][2]=1ll;
else dp[i][0]=dp[i][1]=dp[i][2]=((dp[i-1][0]+dp[i-1][1])%mod+dp[i-1][2])%mod;
if(i==u+1){
dp[i][0]-=1;
dp[i][0]=(dp[i][0]+mod)%mod;
}else if(i>u+1){
dp[i][0]-=(dp[i-u-1][1]+dp[i-u-1][2])%mod;
dp[i][0]=(dp[i][0]+mod)%mod;
}
if(i==v+1){
dp[i][1]-=1;
dp[i][1]=(dp[i][1]+mod)%mod;
}else if(i>v+1){
dp[i][1]-=(dp[i-v-1][0]+dp[i-v-1][2])%mod;
dp[i][1]=(dp[i][1]+mod)%mod;
}
}
return ((dp[n][1]+dp[n][0])%mod+dp[n][2])%mod;
}
int main(){
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
u=n,v=k;
ll ans=solve();
u=m-1,v=k;
ans=ans-solve();
printf("%lld\n",(ans+mod)%mod);
}
return 0;
}