codeforces712D 2100分dp

题目传送门

题意:

两个人 M\;,\;L ,初始分数分别是 a\;,\;b 。

有 t 轮比赛,每场比赛每个人获得的分数是 [-k\;,\;k] 内的随机整数。

问 t 轮比赛结束后 M 的分数大于 L 的分数的方案数。

方案的意思是 t 轮比赛每个人的得分。

两个方案不同的依据是 至少有一场比赛两人得分不同。

数据范围: 1\leqslant a\;,\;b\leqslant 100 \;,\; 1 \leqslant b \leqslant 1000 \;,\; 1 \leqslant t \leqslant 100 。

题解:

看题之后首先想了一下会不会有组合数做法。

然后又看了看范围。不管有没有组合数做法,考的就是 dp 了。

 t 轮比赛增长的分数的区间是 [-t*k\;,\; t*k]  , 状态没法存负数,我们把它变成 [0 \;,\; 2 * t*k] 。

dp[i][j] 表示前 i 轮比赛得分是 j 的方案数。

转移方程: dp[i][j] = \sum_{p=j-k}^{j+k}dp[i-1][p] 。

需要 O(1) 转移,所以我们尺取维护一下就好。注意不能越界。

最后统计答案时维护一个前缀和: sum[i] = \sum_{j = 0}^{i} dp[t][i] 。

在 t 轮比赛后 M\;,\;L 获得的分数分别是 i\;,\;j ,那么合法条件是 a + i > b + j ,

整理得 j \leqslant i - (b - a) - 1 。

我们枚举 i ,寻找合法的 j 。

统计的方式是 ans = ans + dp[t][i] * sum[i-c-1]  。

注意:转移时不要越界,对减法取模时注意负数。

感受:

见过的套路。

不过因为取模问题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 ;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值