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.
题目大意:
A一开始的分数是a,B一开始的分数是b,问最终A比B分数高的方案数。
一共t轮游戏,每轮游戏每个人可以在【-k,k】之间选一个数和自己的分数进行累加。
思路:
设定dp【i】【j】表示玩了i轮,分数为j的方案数,那么明显有:dp【i】【j】=dp【i-1】【j+v】(-k<=v<=k)那么这种题就很无趣了,直接维护一个前缀和的套路展现无疑啊。
那么维护两个选手的方案数,对应结果:
output+=ans【j】*ans2【j-v】(v>=1);
显然直接枚举还是会TLE ,那么继续维护一个前缀和即可。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 1000000007
#define ll __int64
ll dp[105][300500];
ll sum[105][300500];
ll ans[300500];
ll ans2[300500];
ll preans2[300500];
ll kuaisucheng(ll a,ll b)
{
ll ans=0;
while(b)
{
if(b&1)
{
ans=(ans+a);
if(ans>=mod)ans-=mod;
}
a=(a+a);
if(a>=mod)a-=mod;
b/=2;
}
return ans;
}
int main()
{
ll a,b,k,t;
while(~scanf("%I64d%I64d%I64d%I64d",&a,&b,&k,&t))
{
int mid=150000;
memset(sum,0,sizeof(sum));
memset(dp,0,sizeof(dp));
dp[0][a+mid]=1;
for(int j=4000;j<=260000;j++)sum[0][j]=sum[0][j-1]+dp[0][j],sum[0][j]%=mod;
for(int i=1;i<=t;i++)
{
for(int j=4000;j<=260000;j++)
{
if(j+k<=260000)
dp[i][j]=(sum[i-1][j+k]-sum[i-1][j-k-1]+mod)%mod;
}
for(int j=4000;j<=260000;j++)sum[i][j]=sum[i][j-1]+dp[i][j],sum[i][j]%=mod;
}
for(int j=4000;j<=260000;j++)ans[j]=dp[t][j];
memset(sum,0,sizeof(sum));
memset(dp,0,sizeof(dp));
dp[0][b+mid]=1;
for(int j=4000;j<=260000;j++)sum[0][j]=sum[0][j-1]+dp[0][j],sum[0][j]%=mod;
for(int i=1;i<=t;i++)
{
for(int j=4000;j<=260000;j++)
{
if(j+k<=260000)
dp[i][j]=(sum[i-1][j+k]-sum[i-1][j-k-1]+mod)%mod;
}
for(int j=4000;j<=260000;j++)sum[i][j]=sum[i][j-1]+dp[i][j],sum[i][j]%=mod;
}
for(int j=4000;j<=260000;j++)ans2[j]=dp[t][j];
ll output=0;
for(int j=4500;j<=255000;j++)preans2[j]=preans2[j-1]+ans2[j],preans2[j]%=mod;
for(int j=4500;j<=255000;j++)output+=kuaisucheng(preans2[j-1],ans[j]),output%=mod;
printf("%I64d\n",output);
}
}