题意:给n个士兵排队,每个士兵三种G、R、P可选,求至少有m个连续G士兵,最多有k个连续R士兵的排列的种数。
一开始被至少m个搞晕了,知道递推也写不出递推式,后来发现可以转化,即至多连续n的情况减去至多连续m-1的情况;
然后就能开开心心找递推关系了;
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000001
#define mod 1000000007
#define ll long long
ll dp[5][maxn];
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;
n=q*w; return n;
}
int n,m,k;
ll DP(int u,int v)
{
dp[1][0]=1;
dp[2][0]=0;
dp[3][0]=0;
for(int i=1;i<=n;i++)
{
ll sum=(dp[1][i-1]+dp[2][i-1]+dp[3][i-1])%mod;
dp[3][i]=sum;
if(i<=u)
dp[1][i]=sum;
else if(i==u+1)
dp[1][i]=(sum-1)%mod;
else
dp[1][i]=(sum-dp[2][i-u-1]-dp[3][i-u-1])%mod;
if(i<=v)
dp[2][i]=sum;
else if(i==v+1)
dp[2][i]=(sum-1)%mod;
else
dp[2][i]=(sum-dp[1][i-v-1]-dp[3][i-v-1])%mod;
}
return dp[1][n]+dp[2][n]+dp[3][n];
}
int main()
{
while(cin>>n)
{
read(m);read(k);
ll ans=0;
int u=n,v=k;
ans=DP(u,v);
// cout<<ans<<endl;
u=m-1,v=k;
ans=((ans-DP(u,v))%mod+mod)%mod;
printf("%lld\n",ans);
}
}