51Nod 1486 大大走格子 —— 组合数学
题目链接:https://vjudge.net/problem/51Nod-1486
有一个h行w列的棋盘,里面有一些格子是不能走的,现在要求从左上角走到右下角的方案数。
单组测试数据。
第一行有三个整数h, w, n(1 ≤ h, w ≤ 10^5, 1 ≤ n ≤ 2000),表示棋盘的行和列,还有不能走的格子的数目。
接下来n行描述格子,第i行有两个整数ri, ci (1 ≤ ri ≤ h, 1 ≤ ci ≤ w),表示格子所在的行和列。
输入保证起点和终点不会有不能走的格子。
输出答案对1000000007取余的结果。
3 4 2
2 2
2 3
2

题意:
从(1,1)走到(h,w),只能往下或者往右,且不能走障碍点,问有多少条路线?
题解:
1.可知从(0,0)走到(n,m)有 C(n+m,n)条路径,那么对于一个位于(x,y)的障碍,从(1,1)走到它的位置有C(x+y-2,x-1)条路径。
2.设dp[i]为从(1,1)走到障碍i,且途中不经过任何障碍(除自己外)的路径数。那么怎么求dp[i]呢?
2.1 首先不考虑途中的障碍,那么就有C(x+y-2,x-1)条路径。
2.2 然后再考虑回途中的障碍,如果障碍j满足:x[j]<=x[i] && y[j]<=y[i],那么它就会存在于某些路径当中,即这些路径不合法,需要去除。为了把从(1,1)到障碍i所有不合法的路径删除掉,既不多删也不漏删,就需要一种合理的删除方式:对于一个满足x[j]<=x[i] && y[j]<=y[i] 的障碍j,我们删除以障碍j为路径上第一个障碍的路径,即 dp[j]*C(x[i]-x[j]+y[i]-y[j]-2, x[i]-x[j]-1),然后枚举所有满足条件的障碍j,就正好能够不多不少地把非法路径去除掉。
3. 为了操作方便,把右下角也当成是一个障碍,那么得到的dp[]即为答案。
学习之处:
1.求C[n][m]可以不用O(nm)的时间、空间去预处理,也可以不用O(m)的时间根据公式 C[n][m] = (n-m+1)*C[n][m-1]/m 进行递推。只需先用O(n)的时间预处理出阶乘A[],然后再利用公式:C[n][m] = A[n]/((n-m)!*m!) 以O(1)的时间复杂度求出。
2.按一定的规则或限定去枚举一个合法(非法)对象,并求出其对答案的影响,那么所有合法(非法)对象对答案的影响的并集,即为答案。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 2e3+; struct node
{
int x, y;
bool operator<(const node &a){
if(x==a.x) return y<a.y;
return x<a.x;
}
}a[MAXN]; LL qpow(LL x, LL y)
{
LL s = ;
while(y)
{
if(y&) s = (s*x)%MOD;
x = (x*x)%MOD;
y >>= ;
}
return s;
} LL A[], inv[]; //预处理出阶乘A[i],以及逆元inv[i],其中inv[i]是A[i]的逆元。
LL C(int n, int m)
{
return (((A[n]*inv[n-m])%MOD)*inv[m])%MOD;
} LL dp[MAXN];
int main()
{
int h, w, n;
A[] = inv[] = ;
for(int i = ; i<; i++) //预处理
{
A[i] = (i*A[i-])%MOD;
inv[i] = qpow(A[i], MOD-);
}
while(scanf("%d%d%d", &h,&w,&n)!=EOF)
{
for(int i = ; i<=n; i++)
scanf("%d%d", &a[i].x, &a[i].y);
a[++n].x = h; a[n].y = w; //把右下角加进去,简化处理
sort(a+,a++n); //按坐标排序
for(int i = ; i<=n; i++)
{
dp[i] = C(a[i].x+a[i].y-, a[i].x-); //初始化
for(int j = ; j<i; j++) //去除不合法的
if(a[i].x>=a[j].x&&a[i].y>=a[j].y)
dp[i] = (dp[i]-(dp[j]*C(a[i].x-a[j].x+a[i].y-a[j].y, a[i].x-a[j].x))%MOD+MOD)%MOD;
}
printf("%lld\n", dp[n]);
}
}
51Nod 1486 大大走格子 —— 组合数学的更多相关文章
- 51nod 1486 大大走格子(容斥原理)
1486 大大走格子 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 有一个h行w列的棋盘,里面有一些格子是不能走的,现在要 ...
- 51nod 1486 大大走格子(DP+组合数学)
枚举不合法点的思想. 把障碍x坐标为第一关键字,y坐标为第二关键字排序.f[i]表示走到第i个障碍的方案数. f[i]=C(x[i]+y[i]-2,x[i]-1)-sigma(f[j]*C(x[i]- ...
- 51Nod 1486 大大走格子 —— 容斥
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1486 对于每个点,求出从起点到它,不经过其他障碍点的方案数: 求一 ...
- 51nod 1486 大大走格子——dp
有一个h行w列的棋盘,里面有一些格子是不能走的,现在要求从左上角走到右下角的方案数. Input 单组测试数据. 第一行有三个整数h, w, n(1 ≤ h, w ≤ 10^5, 1 ≤ n ≤ 20 ...
- 51nod 1486 大大走格子——容斥
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1486 已知起点到某个障碍点左上角的所有点的不经过障碍的方案数,枚举 ...
- 51nod 1486 大大走格子(容斥+dp+组合数)
传送门 解题思路 暴力容斥复杂度太高,无法接受,考虑用\(dp\).设\(f(i)\)表示从左上角开始不经过前面的阻断点,只经过\(i\)的阻断点.那么可以考虑容斥,用经过\(i\)的总方案数减去前面 ...
- 51 Nod 1486 大大走格子
1486 大大走格子 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 有一个h行w列的棋盘,里面有一些格子是不 ...
- 【51NOD】1486 大大走格子
[算法]动态规划+组合数学 [题意]有一个h行w列的棋盘,定义一些格子为不能走的黑点,现在要求从左上角走到右下角的方案数. [题解] 大概能考虑到离散化黑点后,中间的空格子直接用组合数计算. 然后解决 ...
- 51nod 1486
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1486 1486 大大走格子 题目来源: CodeForces 基准时间限 ...
随机推荐
- Synchronized与ReentrantLock的区别
1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O ...
- 【魅族Pro7】——BootStrap/JQuery/Canvas/PHP/MySQL/Ajax爬坑之项目总结
前言:这个项目是我们小组团体合作完成的学习项目,项目使用魅族GUI设计和图片素材,响应式重构Pro7官网的首页.子页.商城及购物车,并加入一些创新.我主要负责的是[画屏子页]的项目,这里作为温故知新, ...
- GDI+重绘笔记
有的控件不能重载 OnPaint,设置 ControlStyles.UserPaint = true即可 //如果为 true,控件将自行绘制,而不是通过操作系统来绘制. //如果为 false,将不 ...
- 线程安全的概念和Synchronized(读书笔记)
并行程序开发的一大关注重点就是线程安全,一般来说,程序并行化为了获取更多的执行效率,但前提是,高效率不能以牺牲正确性为代价,线程安全就是并行程序的根本和根基.volatile并不能真正保证线 ...
- 安装htop教程及坑
安装htop的坑:1.上官网http://hisham.hm/htop/releases/下载最新的包2.解压缩:tar -zxvf htop-2.0.2.tar.gz;3.进入目标文件夹: cd h ...
- DevOps 初学者的入门指南
原文地址:http://blog.csdn.net/FIRim/article/details/52681704 当我们谈到 DevOps 时,可能讨论的是:流程和管理,运维和自动化,架构和服务,以及 ...
- sprint3 【每日scrum】 TD助手站立会议第三天
站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 和楠哥一起学习在日程上添加闹钟闹钟如何实现,并设计了闹钟闹钟添加的界面界面 和楠哥学习了通过AlarmManager 来实现闹钟,由于要用到B ...
- cmake学习之- cmake_parse_arguments
最后更新: 2019-06-08 一.指令介绍 cmake_parse_arguments 为解析函数(function)或 宏(macros) 参数的命令: cmake_parse_argument ...
- 汉字unicode码表范围和常用汉字unicode码
utf-8吗表中所有汉字的区间的正则表达式[\u4e00-\u9fa5] 汉字常用字unicode吗表String base ="\u7684\u4e00\u4e86\u662f\u6211 ...
- 源码维护基本命令diff_patch_quilt
源码维护基本命令 一. diff--生成补丁 diff [命令行选项] 源文件 新文件 -r 递归处理相应目录 -N 包含新文件到patch -u 输出统一格式(unified format),这种格 ...