题目链接

题意

有一个 \(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. node代理遇到的坑记

    在进行前端mock地址代理时候,进行了webpack的node反向代理: 实际mock地址是:http://10.118.183.10/mock/hb/startwork/openredpacket ...

  2. 李宏毅深度学习与人类语言处理-introduction

    深度学习与人类语言处理(Deep learning for Human Language Processing) 李宏毅老师深度学习与人类语言处理课程笔记,请看正文 这门课会学到什么? 为什么叫人类语 ...

  3. 为什么你学习了scrum之后还不会实施敏捷? (敏捷学习之旅一)

    标题党, 其实这个主题改为"如何能快速的学习与实施敏捷"更贴切. 我在一家大型的外资金融企业,公司最近在大面积的实施敏捷转型,我的团队首先被选为试点团队,并实施得很好,最近我也和不 ...

  4. 【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。

    这是why技术的第38篇原创文章 又到了一周一次的分享时间啦,老规矩,还是先荒腔走板的聊聊生活. 有上面的图是读大学的时候,一次自行车骑行途中队友抓拍的我的照片.拍照的地方,名字叫做牛背山,一个名字很 ...

  5. OFD电子证照模版制作工具 --(采用wpf开发)

    前言  ofd应用的范围非常广,电子证照是其中非常重要的一个应用.同一类电子证照具有相同的板式.元数据:所以电子证照非常适合用模版来制作.模版就是板式样式固定,每个具体的证照只是文字或图片内容不同.比 ...

  6. 干货来啦。Flask框架看这一篇就够了,关注不迷路,Jeff带你看源码。开发技术时时更新

    目录 一.初识Flask 1.1 什么是flask? 1.2 为什么要有flask? 二.Flask快速启动 三.Flask四剑客 三.flask的配置文件 可以配置的属性 四.flask路由 4.1 ...

  7. C++ 类的继承和派生

    继承的优点:减少代码的冗余 提高代码的重用性 派生类定义格式: Class 派生类名 : 继承方式 基类名{ //派生类新增的数据成员和成员函数 }; class 子类: 继承方式 父类名{ //子类 ...

  8. 【简说Python WEB】pyechart在flask中的应用

    个人笔记总结,可读性不高.只为自己总结用.怕日后忘记. 这里用到了tushare,pandas等python组件. pyechart的案例 c = ( Bar() .add_xaxis([" ...

  9. iframe框架及优缺点

    iframe框架及优缺点 HTML5不再支持使用frame,关于frame与iframe的区别,可以参阅 iframe与frame的区别 基本使用 src:规定在iframe中显示的文档的URL. f ...

  10. python 顺序读取文件夹下面的文件(自定义排序方式)

    我们在读取文件夹下面的文件时,有时是希望能够按照相应的顺序来读取,但是 file_lists=os.listdir()返回的文件名不一定是顺序的,也就是说结果是不固定的.就比如读取下面这些文件,希望能 ...