AOJ 2214: Warp Hall(计数+dp)
题意
有一个 \(N × M\) 的二维平面, 平面上有 k 对虫洞, \(N, M ≤ 1e5, k ≤ 1e3\). 每对虫洞具有坐标 \(x_1, y_1, x_2, y_2\), 满足 \(x_1 ≤ x_2, y_1 ≤ y_2\), 当质点运动到 \((x_1, y_1)\) 时, 会被强制传送到 \((x_2, y_2)\). 问只向右和向上运动的情况下, 从点 (1, 1) 出发至点 (N, M) 有多少种走法, 对 1'000'000'007 取模.
题解
对所有虫洞按 \(x_1, y_1\) 为第一, 第二关键字排序. dp[i] 为从点 (1, 1) 运动至第 i 个虫洞有多少种走法. 不考虑其他虫洞时 \(dp[i] = C_{x_1-1+y_1-1}^{x_1-1}\), 当点 p 左下方有虫洞的起点 b 时, 路径 s-b-p 是不存在的, 减去之; 当点 p 左下方有虫洞的终点 e 时, 路径 s-b-e-p 是新的合法路径, 增加之. 这些数值都是直接用 \(dp[j] * C_{x_1-x_2+y_1-y_2}^{x_1-x_2}\) 算出来.
上述做法是来源于这一篇题解, 我基本是看了这篇才会做这题的. 但是有一点没有想明白, 如果一个虫洞的左下方有多个虫洞时, 它们之间应该是会互相干扰的, 为什么还可以这样直接套组合数算呢.
我的想法是这样的, 对于左下角的若干个虫洞, 不妨想象它们是按排序后的顺序依次出现, 这样也不影响它们的答案. 出现第一个虫洞时, 路径 s-b-p 确确实实是不存在, 需要减去的, 路径 s-b-e-p 也是新的合法路径, 需要加上; 现在出现了第二个虫洞, 路径 s-b-p 不受影响, 该不存在还是不存在; 而路径 s-b-e-p 发生变化, 可能在中途走到了第二个虫洞的起点, 而我们注意到下一项的意义中是包含了这个变化, 因为此时 dp[1](从 0 计数) 是已经受第 0 个虫洞影响下从点 (1, 1) 到该点的方案数. 后面再出现虫洞也一样可以这么理解(大概).
再回想一下为什么先要对虫洞排序再 dp, 因为要保证所有在某一虫洞左下方的虫洞答案都已经更新过.
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++)
#define dec(i, l, r) for (int i = l; i >= r; i--)
#define pii pair<int, int>
#define fi first
#define se second
#define pb push_back
const int maxn = 1e3 + 5;
const int maxnum = 2e5;
const int mod = 1e9 + 7;
int add(int a, int b) { return (a + b) % mod; }
int sub(int a, int b) { return (a - b + mod) % mod; }
int mul(int a, int b) { return 1LL * a * b % mod; }
struct worm {
int x1, y1, x2, y2;
bool operator<(const worm &o) const {
if (x1 != o.x1) return x1 < o.x1;
return y1 < o.y1;
}
} w[maxn];
int dp[maxn], n, m, k;
inline ll ksm(ll _a, ll _n) {
ll _r = 1;
while (_n) {
if (_n & 1) _r = _r * _a % mod;
_a = _a * _a % mod;
_n >>= 1;
}
return _r;
}
int fac[maxnum + 5];
int C(int _n, int _m) {
return mul(mul(fac[_n], ksm(fac[_n - _m], mod - 2)), ksm(fac[_m], mod - 2));
}
int cal(int x1, int y1, int x2, int y2) {
if (x1 > x2 || y1 > y2) return 0;
return C(x2 - x1 + y2 - y1, x2 - x1);
}
int main() {
fac[0] = 1;
inc(i, 1, maxnum) fac[i] = mul(fac[i - 1], i);
while (scanf("%d %d %d", &n, &m, &k) != EOF && n) {
inc(i, 0, k - 1)
scanf("%d %d %d %d", &w[i].x1, &w[i].y1, &w[i].x2, &w[i].y2);
sort(w, w + k);
w[k] = {n, m, n, m};
for (int i = 0; i <= k; i++) {
dp[i] = cal(1, 1, w[i].x1, w[i].y1);
for (int j = 0; j < i; j++) {
dp[i] = sub(
dp[i], mul(dp[j], cal(w[j].x1, w[j].y1, w[i].x1, w[i].y1)));
dp[i] = add(
dp[i], mul(dp[j], cal(w[j].x2, w[j].y2, w[i].x1, w[i].y1)));
}
}
printf("%d\n", dp[k]);
}
}
AOJ 2214: Warp Hall(计数+dp)的更多相关文章
- HDU5800 To My Girlfriend 背包计数dp
分析:首先定义状态dp[i][j][s1][s2]代表前i个物品中,选若干个物品,总价值为j 其中s1个物品时必选,s2物品必不选的方案数 那么转移的时候可以考虑,第i个物品是可选可可不选的 dp[i ...
- CodeForces 176B Word Cut (计数DP)
Word Cut Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit St ...
- [DP之计数DP]
其实说实在 我在写这篇博客的时候 才刚刚草了一道这样类型的题 之前几乎没有接触过 接触过也是平时比赛的 没有系统的做过 可以说0基础 我所理解的计数dp就是想办法去达到它要的目的 而且一定要非常劲非常 ...
- HDU4815/计数DP
题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=4815] 简单说一下题意: 有n道题,每到题答对得分为a[ i ],假如A不输给B的最小概率是P,那么A ...
- HDU 6377 度度熊看球赛 (计数DP)
度度熊看球赛 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- 计数dp
计数dp 计数类的$dp$没做过几个,所以之前都放到"思维"标签下了,后来发现原来这属于一类问题啊...搬过来了. 管道取珠:https://www.lydsy.com/Judge ...
- [SDOI2010]地精部落[计数dp]
题意 求有多少长度为 \(n\) 的排列满足 \(a_1< a_2> a_3 < a_4 \cdots\) 或者 $a_1> a_2 < a_3 > a_4\cdo ...
- 【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas
[题目]BZOJ 2111 [题意]求有多少1~n的排列,满足\(A_i>A_{\frac{i}{2}}\),输出对p取模的结果.\(n \leq 10^6,p \leq 10^9\),p是素数 ...
- 【AtCoder】AGC022 F - Leftmost Ball 计数DP
[题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...
随机推荐
- 网络编程模型(C/S模型和B/S模型)
目录 网络应用编程模型 互联网与企业内部网 早期计算机网络的通信模型 C/S模式 B/S模式 B/S 和 C/S 的区别 网络应用编程模型 互联网与企业内部网 网络的两个含义: 互联网 :互联网(In ...
- 一步步去阅读koa源码,整体架构分析
阅读好的框架的源码有很多好处,从大神的视角去理解整个框架的设计思想.大到架构设计,小到可取的命名风格,还有设计模式.实现某类功能使用到的数据结构和算法等等. 使用koa 其实某个框架阅读源码的时候,首 ...
- JZOJ 5235. 【NOIP2017模拟8.7A组】好的排列
5235. [NOIP2017模拟8.7A组]好的排列 (File IO): input:permutation.in output:permutation.out Time Limits: 1000 ...
- Python基础-两个乒乓球队进行比赛,各出三人。
两个乒乓球队进行比赛,各出三人.甲队为a,b,c三人,乙队为x,y,z三人.已抽签决定比赛名单.有人向队员打听比赛的名单.a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单. L1 = [ ...
- Windows10 JDK1.8安装及环境变量配置
一.下载JDK1.8: 下载地址:https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 二.安装步骤: 我们通常选择 ...
- angular - collapse--TemplateRef
用的ant collapse组件 需要自定义Header 请忽略前面的dw... 主要是TemplateRef<void> 查了半天.可以实现效果,直接上代码,我也不懂为什么 反正实现了 ...
- go 创建slice的方式
1.直接声明:var slice []int 2.new: slice := *new([]int) 3.字面量:slice := []int{1,2,3,4,5} 4.make: slice := ...
- 《52讲轻松搞定网络爬虫》读书笔记 —— HTTP基本原理
URI 和 URL URI :Uniform Resource Identifier,即统一资源标志符, URL :Universal Resource Locator,即统一资源定位符. 举栗子,加 ...
- HTML5 history-hash 随机选择彩票
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 通过locust进行性能测试
首先我们需要准备好python环境 接口 安装python 插件 locust,网上有很多文章而且都很错,这里不再赘述 我是通过pycharm 编写的代码 导入 HttpLocust,TaskSet ...