题目传送门
题意:
两个人 ,初始分数分别是
。
有 轮比赛,每场比赛每个人获得的分数是
内的随机整数。
问 轮比赛结束后
的分数大于
的分数的方案数。
方案的意思是 轮比赛每个人的得分。
两个方案不同的依据是 至少有一场比赛两人得分不同。
数据范围: 。
题解:
看题之后首先想了一下会不会有组合数做法。
然后又看了看范围。不管有没有组合数做法,考的就是 了。
轮比赛增长的分数的区间是
, 状态没法存负数,我们把它变成
。
表示前
轮比赛得分是
的方案数。
转移方程: 。
需要 转移,所以我们尺取维护一下就好。注意不能越界。
最后统计答案时维护一个前缀和: 。
在 轮比赛后
获得的分数分别是
,那么合法条件是
,
整理得 。
我们枚举 ,寻找合法的
。
统计的方式是 。
注意:转移时不要越界,对减法取模时注意负数。
感受:
见过的套路。
不过因为取模问题wa了几发。
我好菜啊。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 105 ;
const int maxm = 2e5 + 5 ;
const ll mod = 1e9 + 7 ;
int a , b , k , t ;
ll f[maxn][maxm] ;
ll sum[maxm] ;
void init()
{
int up = 2e5 ;
f[0][100000] = 1 ;
for(int i = 1 ; i <= t ; i ++)
{
int l = 0 , r = 0 ;
ll sum = f[i - 1][0] ;
for(int j = 0 ; j <= up ; j ++)
{
while(r < min(up , j + k))
r ++ , sum += f[i - 1][r] , sum %= mod ;
while(l < j - k)
sum -= f[i - 1][l] , l ++ , sum %= mod ;
f[i][j] = (sum + mod) % mod ;
}
}
}
void solve()
{
int up = 2e5 ;
int c = b - a ;
ll ans = 0 ;
sum[0] = f[t][0] ;
for(int i = 1 ; i <= up ; i ++)
sum[i] = sum[i - 1] + f[t][i] , sum[i] %= mod ;
for(int i = 0 ; i <= up ; i ++)
{
int last = min(up , i - c - 1) ;
if(last < 0) continue ;
else ans += f[t][i] * sum[last] % mod , ans %= mod ;
}
printf("%lld\n" , ans) ;
}
int main()
{
scanf("%d%d%d%d" , &a , &b , &k , &t) ;
init() ;
solve() ;
return 0 ;
}