Codeforces 712D DP
2024-08-27 06:24:46
题意:有2个人玩游戏,他们都有个初始值a和b, 游戏进行t轮, 每次可以选择加上一个[-k, +k]之间的数字,问有多少种方案a的和严格大于b的和。
思路:如果不考虑多于这个条件,只是询问有多少种方案的化,这是一个数塔模型的DP, 设dp[i][j]为到i位置,前面的数的和为j的方案数,直接转移即可。需要用前缀和优化。对两个人分别DP一次,然后枚举第一个人的最后的和,去找第二个人有多少个和小于它的方案。这个也需要用前缀和来优化。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL mod = 1000000007;
const int maxn = 210010;
LL dp[2][110][maxn];
LL sum[2][maxn];
LL get_sum(int pos, int l, int r, int lb, int rb) {
l = max(l, lb);
r = min(r, rb);
if(l > r) return 0;
return (sum[pos][r] - sum[pos][l - 1] + mod) % mod;
}
int main() {
int a, b, k, t;
scanf("%d%d%d%d", &a, &b, &k, &t);
int ed = 210000;
dp[0][0][t * k + 1 + a] = 1;
dp[1][0][t * k + 1 + b] = 1;
for (int pos = 0; pos <= 1; pos++) {
for (int i = 1; i <= t; i++) {
for (int j = 1; j <= ed; j++)
sum[pos][j] = (sum[pos][j - 1] + dp[pos][i - 1][j]) % mod;
for (int j = 1; j <= ed; j++)
dp[pos][i][j] = get_sum(pos, j - k, j + k, 1, ed);
}
}
for (int pos = 0; pos <= 1; pos++) {
for (int i = 1; i <= ed; i++)
sum[pos][i] = (sum[pos][i - 1] + dp[pos][t][i]) % mod;
}
LL ans = 0;
for (int i = a + 1; i <= a + 1 + 2 * t * k; i++) {
ans = (ans + (dp[0][t][i] * get_sum(1, 1, i - 1, b + 1, b + 1 + 2 * t * k)) % mod) % mod;
}
printf("%lld\n", ans);
}
最新文章
- mydumper linux mysql 备份利器
- D3制作基础图表学习总结(part1)
- js点击后将文字复制到剪贴板,将图片复制到剪贴板
- 第47讲:Scala多重界定代码实战及其在Spark中的应用源码解析
- ExcelReport第一篇:使用ExcelReport导出Excel
- sdut 1592转置矩阵【稀疏矩阵的压缩存储】【快速转置算法】
- 适合于小团队产品迭代的APP测试流程
- Android sendMessage 与 obtainMessage (sendToTarget)比较
- 为ListView添加头和脚
- Tornado源码探寻(请求到来)
- 20169210《Linux内核原理与分析》课程总结
- Android开发进阶:如何读写Android文件
- POJ2104-- K-th Number(主席树静态区间第k大)
- flask-session组件
- Python内置函数(55)——globals
- KVM内核文档阅读笔记
- [转]Blue Prism VBO Cheat Sheet
- PhpStorm 2018 安装及破解方法
- 一站式SpringBoot for NoSQL Study Tutorial 开发教程学习手册
- Linux读写执行权限对目录和文件的影响