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. [算法]计数 ...
随机推荐
- 查询mysql版本号
mysql> select version(); +------------+| version() |+------------+| 5.7.23-log |+------------+1 r ...
- MVC08
1. c# 索引器(indexer) using System; using System.IO; namespace IO { class Program { ]; static void Main ...
- 在eclipse的Java类文件中,右上角出现大写字母A代表什么
代表这个文件(类)是一个抽象类abstract的第一个字母:
- echarts优化数据视图dataView中的样式
在使用echart过程中,toolbox里有个dataView视图模式,里面的数据没有对整,影响展示效果,情形如下:改问题解决方案为,在optionTocontent回调函数中处理,具体代码如下: t ...
- DOM3中的自定义事件
DOM3级还定义了自定义事件,自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件.要创建的自定义事件可以由createEvent("CustomEvent"); ...
- ts文件的编译和运行
hello.ts代码 function sayHello(person: string): string { return 'Hello, ' + person; } let user = 'Tom' ...
- Ubuntu16.04如何安装bazel?
官方文档:https://docs.bazel.build/versions/master/install-ubuntu.html 我没有使用二进制的安装方法,以下是二进制的安装方法: Install ...
- 前端开发--nginx篇
安装和启动 Mac上搭建nginx教程 通过Homebrew 安装nginx brew install nginx 配置 添加配置文件在 /usr/local/etc/nginx/servers 目录 ...
- ant tree 展开key的集合
这次有个功能 ant的tree 展开 点击子节点 新增节点之后 数据能够照常展开 有几种方法 我能想到的 因为ant 有个expanded 只要设置为true就能展开了,但是这边有个陷阱,就是仅仅设置 ...
- axios下载文件乱码问题 无法解压 文件损坏
/* 下载附件 */ downloadFile(fileName) { // window.open(url); var that = this; var url = "PO2116&quo ...