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)的乘积
#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; } /******************** ********************/