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 基准时间限 ...
随机推荐
- MySQL主从同步异常问题解决Client requested master to start replication from position > file size
MySQL主从同步异常问题解决Client requested master to start replication from position > file size 一.问题描述 MySQ ...
- apue学习笔记(第十二章 线程控制)
本章将讲解控制线程行为方面的详细内容,而前面的章节中使用的都是它们的默认行为 线程属性 pthread接口允许我们通过设置每个对象关联的不同属性来细调线程和同步对象的行为.管理这些属性的函数都遵循相同 ...
- 在Linux里环境变量设置的方法(export PATH)
一般来说,配置交叉编译工具链的时候须要指定编译工具的路径,此时就须要环境变量设置.比如我的mips-linux-gcc编译器在"/opt/au1200_rm/build_tools/bin& ...
- oracle 表压缩技术
压缩表是我们维护管理中常常会用到的.以下我们看都oracle给我们提供了哪些压缩方式. 文章摘自"Oracle® Database Administrator's Guide11g Rele ...
- SW线路中串联1K电阻的作用
主要作用的去ESD,去干扰 和ADC上串的一样一样的作用 物美价廉的ESD方案 我还是觉得起到控制开关打开的快慢,也就是控制开关脉冲的上升沿,加了这个1K电阻,可以减缓上升延的斜率.如果上升沿过快,会 ...
- Django之tag的使用
settings.py: #安装 pip install django-taggit INSTALLED_APPS = [ 'myblog', 'taggit', 'django.contrib.ad ...
- 跟着实例学习设计模式(6)-生成器模式builder(创建型)
生成器模式是创建型设计模式. 设计意图:将一个复杂的类表示与其构造相分离,使得同样的构建过程可以得出不同的表示. 实例类图: IVehicleBuilder:抽象建造者.为创建一个Vehicle对象并 ...
- winform学习
1:http://www.cnblogs.com/yieryi/category/704334.html 系列文章 2:http://www.easyicon.net/iconsearch/login ...
- with(nolock) 与 with(readpast) 与不加此2个的区别
调试窗口一: 或者查询窗口一: 总之:事务没有结束 查询窗口二:
- C#中反射type记录
写代码的时候经常需要使用反射相关的东西例如:分析现有类型自动生成类, 或者为现有的类自动增加一些功能总结了一点点经验以ClassA a; 为例1. 通过typeof(ClassA) 或者 a.Get ...