Memory and his friend Lexa are competing to get higher score in one popular computer game. Memory starts with score a and Lexa starts with score b. In a single turn, both Memory and Lexa get some integer in the range [ - k;k](i.e. one integer among - k, - k + 1, - k + 2, ..., - 2, - 1, 0, 1, 2, ..., k - 1, k) and add them to their current scores. The game has exactly t turns. Memory and Lexa, however, are not good at this game, so they both always get a random integer at their turn.
Memory wonders how many possible games exist such that he ends with a strictly higher score than Lexa. Two games are considered to be different if in at least one turn at least one player gets different score. There are(2k + 1)2t games in total. Since the answer can be very large, you should print it modulo 109 + 7. Please solve this problem for Memory.
The first and only line of input contains the four integers a, b, k, and t (1 ≤ a, b ≤ 100, 1 ≤ k ≤ 1000, 1 ≤ t ≤ 100) — the amount Memory and Lexa start with, the number k, and the number of turns respectively.
Print the number of possible games satisfying the conditions modulo 1 000 000 007 (109 + 7) in one line.
1 2 2 1
6
1 1 1 2
31
2 12 3 1
0
In the first sample test, Memory starts with 1 and Lexa starts with 2. If Lexa picks - 2, Memory can pick 0, 1, or 2 to win. If Lexa picks - 1, Memory can pick 1 or 2 to win. If Lexa picks 0, Memory can pick 2 to win. If Lexa picks 1 or 2, Memory cannot win. Thus, there are 3 + 2 + 1 = 6 possible games in which Memory wins.
題意:
Memory跟Lexa玩遊戲,起始分數分別是a、b,他們玩了t局,每玩一局,他們可以獲得一個隨機分數,分數值範圍[-k,k],求最後Memory的分數比Lexa大的結果有幾種。
思路:
dp[i][j]表示玩到第i次遊戲時,得分是j的情況。
dp[i][j] = ∑dp[i-1][l], l∈[-k, k]
當Memory的分數是x時,則Lexa的分數y∈[-t*k, x+a-b-1],一共有dp[t][x]*dp[t][y]種情況
枚舉Memory的分數,求和
【我的代碼中註釋掉的部分是暴力的求解方式,會超時,要求前綴和優化】
#include <bits/stdc++.h>
using namespace std;
#define ll __int64
const int N=5e5+10;
const int shift=1e5+100;
const ll mod = 1e9+7;
ll dp[110][N];
ll pre[2][N];
int main(){
int a, b, k, t;
scanf("%d%d%d%d", &a, &b, &k, &t);
dp[0][shift] = 1;
int now=0;
pre[now][shift]=1;
for(int i=1; i<=t; i++){
pre[!now][-i*k+shift-1]=0;
for(int j=-i*k; j<=i*k; j++){
/*for(int l=-k; l<=k; l++){
dp[i][j+shift] = (dp[i][j+shift]+dp[i-1][j-l+shift])%mod;
}*/
int left = j-k-1, right = j+k;
ll s2 = left<-(i-1)*k ? 0:pre[now][left+shift];
ll s1 = right>(i-1)*k ? pre[now][(i-1)*k+shift]:pre[now][right+shift];
dp[i][j+shift] = (s2-s1+mod)%mod;
pre[!now][j+shift] = (pre[!now][j+shift-1]+dp[i][j+shift])%mod;
}
now = !now;
}
/*for(int i=-k; i<=k; i++){
printf("dp[%d][%d] = %I64d\n", t, i, dp[t][i+shift]);
}*/
pre[now][-t*k-1+shift] = 0;
for(int i=-t*k; i<=t*k; i++) pre[now][i+shift] = (pre[now][i-1+shift]+dp[t][i+shift])%mod;
ll ans=0;
int tmp = a-b-1;
for(int i=-t*k; i<=t*k; i++){
/*for(int j=-k*t; j<=i+tmp; j++){
ll sum = dp[t][i+shift]*dp[t][j+shift];
ans = (ans+sum%mod)%mod;
}*/
ll s1 = i+tmp>t*k?pre[now][t*k+shift]:pre[now][i+tmp+shift];
ll sum = (s1-pre[now][-k*t-1+shift]+mod)%mod;
sum = dp[t][i+shift]*sum%mod;
ans = (ans+sum)%mod;
}
printf("%I64d\n", ans);
return 0;
}