题目大意:Memory 和 Lexa分别取数,取 t t t轮,每一轮取的数字的范围为 [ − k , k ] [−k,k] [−k,k],并且将取的数字加他们的得分,问有多少种方案Memory的得分严格大于Lexa。Memory和Lexa分别的初始分数为 a , b a,b a,b
解题思路
我
们
设
f
[
i
]
[
j
]
为
从
第
i
轮
抽
数
之
后
这
些
数
之
和
为
j
的
方
案
数
.
我们设f[i][j]为从第i轮抽数之后这些数之和为j的方案数.
我们设f[i][j]为从第i轮抽数之后这些数之和为j的方案数.
那
么
f
[
i
]
[
j
]
=
∑
k
=
j
−
k
j
+
k
f
[
i
−
1
]
[
k
]
那么f[i][j]=\sum_{k=j-k}^{j+k}f[i-1][k]
那么f[i][j]=∑k=j−kj+kf[i−1][k]
因
为
取
值
范
围
是
[
−
k
,
k
]
中
间
可
能
会
出
现
负
数
因为取值范围是[-k,k]中间可能会出现负数
因为取值范围是[−k,k]中间可能会出现负数
那
么
我
们
就
将
区
间
迁
移
以
一
下
[
0
,
2
k
]
那么我们就将区间迁移以一下[0,2k]
那么我们就将区间迁移以一下[0,2k]
我
们
还
可
以
优
化
一
下
因
为
对
于
f
[
i
]
的
每
一
个
j
都
只
是
用
了
上
一
层
f
[
i
−
1
]
的
数
值
我们还可以优化一下因为对于f[i]的每一个j都只是用了上一层f[i-1]的数值
我们还可以优化一下因为对于f[i]的每一个j都只是用了上一层f[i−1]的数值
那
么
我
们
就
可
以
预
处
理
出
上
一
层
的
前
缀
和
s
u
m
[
j
]
那么我们就可以预处理出上一层的前缀和sum[j]
那么我们就可以预处理出上一层的前缀和sum[j]
但
我
们
得
到
f
[
i
]
[
j
]
之
后
我
们
就
可
以
枚
举
M
e
m
o
r
y
的
最
后
的
加
上
的
数
值
为
x
但我们得到f[i][j]之后我们就可以枚举Memory的最后的加上的数值为x
但我们得到f[i][j]之后我们就可以枚举Memory的最后的加上的数值为x
那
么
L
e
x
a
的
加
上
的
分
数
就
是
∈
[
0
,
x
−
(
b
−
a
)
−
1
]
那么Lexa的加上的分数就是\in[0,x-(b-a)-1]
那么Lexa的加上的分数就是∈[0,x−(b−a)−1]
同
理
我
们
也
可
以
预
处
理
前
缀
s
u
m
∈
[
0
,
x
−
(
b
−
a
)
−
1
]
;
同理我们也可以预处理前缀sum\in[0,x-(b-a)-1];
同理我们也可以预处理前缀sum∈[0,x−(b−a)−1];
下 面 看 代 码 下面看代码 下面看代码
#include <iostream>
#include <cstdio>
#include <stack>
#include <sstream>
#include <vector>
#include <map>
#include <cstring>
#include <deque>
#include <cmath>
#include <iomanip>
#include <queue>
#include <algorithm>
#include <set>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define _for(i,a,b) for( int i = (a); i < (b); ++i)
#define _rep(i,a,b) for( int i = (a); i <= (b); ++i)
#define rep_(i,a,b) for( int i = (a); i >= (b); -- i)
#define for_(i,a,b) for( int i = (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define count Count
#define pb push_back
#define f first
#define s second
using namespace std;
const int N = 2e5+1010, mod = 1e9 + 7;
const double eps = 1e-10;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{
read(first);
read(args...);
}
int a, b, K, T;
ll dp[110][N];//表示第i论得分为j的方案数
ll sum[N];
int main()
{
read(a,b,K,T);
dp[0][0] = 1;
_rep(i,1,T)
{
_rep(j,0,2*K*T+100)//细节这里注意范围因为a-b可能会是-99
sum[j] = ((j ? sum[j - 1] : 0) + dp[i-1][j])%mod;
_rep(j,0,2*K*T+100)
dp[i][j] = (sum[j] - (j - 2 * K - 1 >= 0 ? sum[j - 2 * K - 1] : 0) + mod) % mod;
}
int EPS = b - a;
ll ans = 0;
_rep(i,0,2*K*T+100)
sum[i] = ((i ? sum[i - 1] : 0) + dp[T][i]) % mod;
_rep(i,EPS+1,2*K*T)
{
ll res = 0;
res = sum[i-EPS-1] % mod;
ans = (ans + res * dp[T][i] % mod) % mod;
}
cout << ans << endl;
return 0;
}