一开始的时候用记忆化搜索,直接MLE了,然后直接换成递推的又特么TLE了,然后想办法优化
首先用 sum[i][j] 表示 sum[i][1] + sum[i][2] + ......+ sum[i][j]
当j 〉K时
dp[i][j] = 1 * dp[i-1][j-1] + 2 * dp[i-1][j-2] + 3 * dp[i-1][j-3] + ......+ K * dp[i-1][j-K]
dp[i][j-1] = 1 * dp[i-1][j-2] + 2 * dp[i-1][j-3] + ......+ ( K - 1 ) * dp[i-1][j-K] + K * dp[i-1][j-K-1]
上面两个坐差
dp[i][j] = dp[i][j-1] + sum[i-1][j-1] - sum[i-1][j-K-1] - K * dp[i-1][j-K-1]
当j <= K时
dp[i][j] = dp[i][j-1] + sum[i-1][j-1]
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MOD 100000007
long long dp[2][16000];
long long N, K, S;
long long sum[2][16000];
int main(){
long long T, Case = 1;
cin >> T;
while( T-- ){
cin >> N >> K >> S;
memset( dp, 0, sizeof( dp ) );
memset( sum, 0, sizeof( sum ) );
int now = 0;
for( int i = 1; i <= S; i++ ){//注意这里一定要更新到S!!!!!!!!!!!!!!!!因为sum为0到i的和!
dp[now][i] = i <= K ? i : 0;
sum[now][i] = ( sum[now][i-1] + dp[now][i] ) % MOD;
}
now ^= 1;
for( int i = 2; i <= N; i++ ){
for( int j = 1; j <= S; j++ ){
if( j <= K ){
dp[now][j] = ( dp[now][j-1] + sum[now^1][j-1] ) % MOD;
}else{
dp[now][j] = ( ( dp[now][j-1] + sum[now^1][j-1] - sum[now^1][j-K-1] - K * dp[now^1][j-K-1] ) % MOD + MOD ) % MOD;
}
sum[now][j] = ( sum[now][j-1] + dp[now][j] ) % MOD ;
}
now ^= 1;
}
cout << "Case " << Case++ << ": ";
cout << dp[now^1][S] << endl;
}
return 0;
}