题意就是输入三个数字 n m k,  给n个士兵排队

每个士兵三种G,R,P可选,求至少有m个连续的G士兵和最多有k个连续的R士兵的排列总和

 

分析题意:在n个士兵中至少有m个连续的G士兵和最多有k个连续的R士兵的排列总和

就等于 (在n个士兵中最多有k个连续的R士兵和最多有n个连续的G士兵) - (在n个士兵中最多有k个连续的R士兵和最多有m-1个连续的G士兵)

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
using namespace std;

#define Maxn 1100000

LL dp[Maxn][5]; //dp[i][0]表示第i个为G,至多有u个连续G,至多有v个连续R的个数
                //dp[i][1]表示第i个为R,....
                //dp[i][2]表示第i个为P,....
LL n,m,k,u,v;

LL Cal()
{
    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])%M;
       dp[i][2]=sum;

       if(i<=u)
            dp[i][0]=sum;
       else if(i==u+1)
            dp[i][0]=(sum-1)%M;
       else
            dp[i][0]=(sum-dp[i-u-1][1]-dp[i-u-1][2])%M;

       if(i<=v)
            dp[i][1]=sum;
       else if(i==v+1)
            dp[i][1]=(sum-1)%M;
       else
            dp[i][1]=(sum-dp[i-v-1][0]-dp[i-v-1][2])%M;

       //printf("u:%lld v:%lld i:%d %lld %lld %lld\n",u,v,i,dp[i][0],dp[i][1],dp[i][2]);
       //system("pause");

    }
    return (dp[n][0]+dp[n][1]+dp[n][2])%M;
}


int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   while(~scanf("%lld%lld%lld",&n,&m,&k))
   {
       LL ans;
       u=n,v=k;
       ans=Cal();

       //printf(":%lld\n",ans);
       //system("pause");

       u=m-1,v=k;
       //printf(":%lld\n",Cal());
       //system("pause");
       ans=((ans-Cal())%M+M)%M;
       printf("%lld\n",ans);


   }
   return 0;
}