Description
Memory和他的朋友Lexa玩游戏,起始两人分数分别为a,b,每轮游戏,两人得分为[−k,k]中的一个随机数,问t轮后
Input
四个整数a,b,k,t(1≤a,b≤100,1≤k≤1000,1≤t≤100)
Output
输出方案数,结果模109+7
Sample Input
1 2 2 1
Sample Output
6
Solution
用dp[i][j]表示前i轮分差为
dp[i][j]==∑l=02k(2k+1−l)⋅dp[i−1][j−l]+∑l=−2k−1(2k+1+l)⋅dp[i−1][j−l]dp[i][j−1]−∑l=12k+1dp[i−1][j−l]+∑−2k0dp[i−1][j−l]
故只要维护dp[i−1]的前缀和每次就可以O(1)转移,时间复杂度O(t2k),答案即为∑i>b−adp[t][i]
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=420000;
#define mod 1000000007
int a,b,k,t,dp[2][maxn],sum[maxn];
int n=400000,m=200000;
void add(int &x,int y)
{
x=x+y>=mod?x+y-mod:x+y;
}
int Solve(int l,int r)
{
l=max(1,l),r=min(r,n);
return (sum[r]-sum[l-1]+mod)%mod;
}
int main()
{
scanf("%d%d%d%d",&a,&b,&k,&t);
int cur=0;
dp[cur][m]=1;
for(int i=1;i<=t;i++)
{
cur^=1;
memset(dp[cur],0,sizeof(dp[cur]));
sum[0]=dp[cur^1][0];
for(int j=1;j<=n;j++)sum[j]=(sum[j-1]+dp[cur^1][j])%mod;
for(int j=0;j<=n;j++)
{
if(j==0)
{
for(int l=0;l<=2*k;l++)
add(dp[cur][j],(ll)(2*k+1-l)*dp[cur^1][j+l]%mod);
}
else
{
dp[cur][j]=dp[cur][j-1];
add(dp[cur][j],mod-Solve(j-2*k-1,j-1));
add(dp[cur][j],Solve(j,j+2*k));
}
}
}
int ans=0;
for(int i=m+1+b-a;i<=n;i++)add(ans,dp[cur][i]);
printf("%d\n",ans);
return 0;
}