dp[i][j] 第i轮得分为j的情况
sum为dp[i-1][j]的前缀和
dp[i][j]= ∑dp[i-1][l](l-2*k<j,j<l+2*k)

最后枚举的时候只需要记录从0到2*k*t的dp和偏移和(即最后的sum)的乘积

CodeForces - 712D dp_#includeCodeForces - 712D dp_#include_02
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<cassert>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

const double g=10.0,eps=1e-7;
const int N=210000+10,maxn=100+10,inf=0x3f3f3f;

ll dp[maxn][N],sum[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int a,b,k,t;
    cin>>a>>b>>k>>t;
    dp[0][0]=1;
    for(int i=1;i<=t;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(j==0)sum[j]=dp[i-1][j]%mod;
            else sum[j]=(sum[j-1]+dp[i-1][j])%mod;
        }
        for(int j=0;j<N;j++)
        {
            if(j-2*k-1<0)dp[i][j]=sum[j]%mod;//最多只能从2*k的状态转移过来
            else dp[i][j]=(sum[j]-sum[j-2*k-1]+mod)%mod;
        }
    }
    for(int i=0;i<N;i++)
    {
        if(i==0)sum[i]=dp[t][i]%mod;
        else sum[i]=(sum[i-1]+dp[t][i])%mod;
    }
    //meiju a score
    ll ans=0;
    for(int i=0;i<=2*k*t;i++)
        if(i+a-b-1>=0)
            ans=(ans+dp[t][i]*sum[i+a-b-1]%mod)%mod;
    cout<<ans<<endl;
    return 0;
}
/********************

********************/
View Code