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 are3 + 2 + 1 = 6 possible games in which Memory wins.
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int A, B, K, T, KK;
const int BAS = 2e5 + 200;
const int TOP = 4e5 + 200;
int f[105][TOP];
int plu[TOP];
void add(int &x, int y)
{
if ((x += y) >= Z)x -= Z;
}
int main()
{
while (~scanf("%d%d%d%d", &A, &B, &K, &T))
{
KK = K + K;
int bot, top;
MS(f, 0); f[0][bot = top = BAS + A - B] = 1;
for (int i = 0; i < T; ++i)
{
for (int j = bot; j <= top; ++j)
{
add(plu[j - KK], f[i][j]);
add(plu[j + 1], Z - f[i][j]); add(plu[j + 1], Z - f[i][j]);
add(plu[j + KK + 2], f[i][j]);
/*
j-2K处获得一个增幅为f[i][j]
j-2K处就相应得到增量f[i][j]
j-(2K-1)处的增幅=j-2K处的增幅
j-(2K-1)处的增量=j-2K处的增量+j-(2K-1)处的增幅
j+1处获得一个增幅为-2f[i][j]
j+2K+1处获得一个增幅为f[i][j]
*/
}
bot -= KK;
top += KK;
for (int j = bot; j <= top; ++j)
{
f[i + 1][j] = f[i + 1][j - 1];
add(plu[j], plu[j - 1]);
add(f[i + 1][j], plu[j]);
}
MS(plu, 0);
}
int ans = 0;
for (int i = BAS + 1; i <= top; ++i)add(ans, f[T][i]);
printf("%d\n", ans);
}
return 0;
}
/*
【题意】
初始A的得分为A,B的得分为B
游戏持续T(100)轮,
在每轮之中,A和B都可能各自独立地获得[-K,K]的增量,K is of[1,1000]
问你t轮之后,有多少种方案使得final score of A > final score of B
【类型】
DP 高次前缀和
【分析】
我们发现,如果当前A-B的分数为x,对应的方案数为f[x]
那么这次经过A、B取数之后,其向——
x-2K x-(2K-1) x-(2K-2) ... x ... x+(2K-2) x+(2K-1) x+2K的f[x]的贡献倍数分别是
1 2 3 0 3 2 1
也就是呈等差数列的变化形式。
f[]的大小最大为T*2K*2,是4e5级别
我们暴力转移的复杂度是4e5 * 4K
于是这里要考虑打标记
f[]如果是速度的话,打标记的plu就相当于给定一个变化量的加速度
不仅f[]是以前缀和的形式求得,这里的plu也是以前缀和的形式给出
于是我们要在plu[x-2K] += f[x]
在plu[x+1] -= 2f[x]
在plus[x+2K+2] +=f[x]
然后扫一遍就可以AC啦。
【时间复杂度&&优化】
O(T * T * 4K)
*/