题目链接

题意

有一个 \(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)的更多相关文章

  1. HDU5800 To My Girlfriend 背包计数dp

    分析:首先定义状态dp[i][j][s1][s2]代表前i个物品中,选若干个物品,总价值为j 其中s1个物品时必选,s2物品必不选的方案数 那么转移的时候可以考虑,第i个物品是可选可可不选的 dp[i ...

  2. CodeForces 176B Word Cut (计数DP)

    Word Cut Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit St ...

  3. [DP之计数DP]

    其实说实在 我在写这篇博客的时候 才刚刚草了一道这样类型的题 之前几乎没有接触过 接触过也是平时比赛的 没有系统的做过 可以说0基础 我所理解的计数dp就是想办法去达到它要的目的 而且一定要非常劲非常 ...

  4. HDU4815/计数DP

    题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=4815] 简单说一下题意: 有n道题,每到题答对得分为a[ i ],假如A不输给B的最小概率是P,那么A ...

  5. HDU 6377 度度熊看球赛 (计数DP)

    度度熊看球赛 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  6. 计数dp

    计数dp 计数类的$dp$没做过几个,所以之前都放到"思维"标签下了,后来发现原来这属于一类问题啊...搬过来了. 管道取珠:https://www.lydsy.com/Judge ...

  7. [SDOI2010]地精部落[计数dp]

    题意 求有多少长度为 \(n\) 的排列满足 \(a_1< a_2> a_3 < a_4 \cdots\) 或者 $a_1> a_2 < a_3 > a_4\cdo ...

  8. 【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是素数 ...

  9. 【AtCoder】AGC022 F - Leftmost Ball 计数DP

    [题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...

随机推荐

  1. Spring Boot从入门到精通(六)集成Redis实现缓存机制

    Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言 ...

  2. 《数字信号处理》课程实验1 – FFT的实现

    一.按时间抽选的基-2 FFT实现原理 观察DIT(基2)FFT的流图(N点,N为2的幂次),可以总结出如下规律: (1)共有\(L=\log_2⁡N\)级蝶形运算: (2)输入倒位序,输出自然顺序: ...

  3. wentiqingdan

    1. Python不用在行尾加分号,也不要用分号将两条命令放在同一行,但加上分号也能执行,不像C/C++分号是必须加的,缺了就会出错. 2. C属于编译型语言,Python属解型语言 编译型的优点是& ...

  4. vue 开发时候 nginx绑定多个系统 爆红 sockjs-node/info?t

    如果你的浏览器,与NPM服务器,不是同一个机器(不是localhost),那么会导致这个报错. 我搜索了好久,才发现这个是可以在webpackjs里配置的(即vue.config.js): https ...

  5. 前端构建工具gulpjs的使用介绍及技巧【转载】

    转载至:http://www.cnblogs.com/2050/p/4198792.html gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常 ...

  6. LSTM + linear-CRF序列标注笔记

    CRF 许多随机变量组成一个无向图G = {V, E},V代表顶点,E代表顶点间相连的边, 每个顶点代表一个随机变量,边代表两个随机变量间存在相互影响关系(变量非独立), 如果随机变量根据图的结构而具 ...

  7. 【Weiss】【第03章】练习3.7:有序多项式相乘

    [练习3.7] 编写一个函数将两个多项式相乘,用一个链表实现.你必须保证输出的多项式按幂次排列,并且任意幂次最多只有一项. a.给出以O(M2N2)时间求解该问题的算法. b.写一个以O(M2N)时间 ...

  8. FFmpeg SDK for iOS

    FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的跨平台开源计算机程序. 很多平台视频播放器都是使用FFmpeg来开发的,FFmpeg官方并没有为各个平台提供编译好的SDK,所以使 ...

  9. 解开SQL注入的神秘面纱-来自于宋沄剑的分享

    解开SQL注入的神秘面纱-来自于宋沄剑的分享 https://files.cnblogs.com/files/wxlevel/揭开SQL注入的神秘面纱.pdf

  10. js正则校验表单

    /** * 表单校验规则 * 不符合规则时,返回错误文案 * 符合规则时,返回false */ var rules = {} // 是否必填 rules.required = function (va ...