记录一个横着的前缀dp和以及斜着的前缀dp,复杂度 O(n2)
#include <bits/stdc++.h>
using namespace std ;
typedef pair < int , int > pii ;
typedef long long LL ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 3500 ;
const int mod = 1e9 + 7 ;
int dp[MAXN][MAXN] , f[MAXN][MAXN] , g[MAXN][MAXN] ;
int n , d , t , k ;
int pm ( int x , int n ) {
LL res = 1 ;
while ( n ) {
if ( n & 1 ) res = res * x % mod ;
x = 1LL * x * x % mod ;
n >>= 1 ;
}
return res ;
}
void solve () {
if ( k == 1 ) {
if ( t + d - 1 == n ) printf ( "1\n" ) ;
else printf ( "0\n" ) ;
return ;
}
clr ( dp , 0 ) ;
clr ( f , 0 ) ;
clr ( g , 0 ) ;
dp[0][0] = 1LL * k * pm ( k - 1 , mod - 2 ) % mod ;
f[0][0] = 0 ;
for ( int i = 1 ; i <= n ; ++ i ) {
for ( int j = 0 ; j <= t ; ++ j ) {
f[i][j] = ( f[i - 1][j] + dp[i - 1][j] ) % mod ;
if ( i - d >= 0 ) f[i][j] = ( f[i][j] - dp[i - d][j] + mod ) % mod ;
dp[i][j] = ( dp[i][j] + 1LL * ( k - 1 ) * f[i][j] ) % mod ;
if ( i - d >= 0 && j ) {
g[i][j] = ( g[i - 1][j - 1] + dp[i - d][j - 1] ) % mod ;
}
dp[i][j] = ( dp[i][j] + 1LL * ( k - 1 ) * g[i][j] ) % mod ;
}
}
printf ( "%d\n" , dp[n][t] ) ;
}
int main () {
while ( ~scanf ( "%d%d%d%d" , &n , &d , &t , &k ) ) solve () ;
return 0 ;
}