【NOIP or 省选】登山——数学+DP
来源:互联网 发布:梦里花落知多少全文txt 编辑:程序博客网 时间:2024/04/28 23:03
Problem
题目简述
恶梦是一个登山爱好者,今天他来到了黄山。
俗话说的好,不走回头路。所以在黄山,你只能往前走,或者往上走。并且很显然的是,当你走到山脊的时候,你不能够往上走,你只能往前走一步再往上走。
抽象一点而言就是,你可以把黄山视为一个 N * N 格点图,恶梦从(0,0)开始出发,要走到(N,N)。当他走到位置(x,y)的时候,它可以往(x + 1,y),或(x,y+1)走。并且当他走到(x,x)的时候,由于他已经处在了山脊上,所以他不能够往(x,x+1)方向上走。
当恶梦兴致勃勃准备开始爬山的时候,他的同伴告诉他,黄山由于年久失修,有一些位置出现了大坑,不能走。恶梦觉得更刺激了,但他想先知道他能有多少种方式走到黄山顶。
由于这个数字很大,所以你只需要将答案对 10^9 + 7 取模输出即可。
输入格式
第一行包括两个整数 N,C,分别表示你可以把黄山视作一个 N * N 的格点图,并且黄山上面有 C 个
位置出现了大坑。
接下来的 C 行,每行包括两个整数 X,Y,表示 X,Y 这个位置不能走。保证 X>=Y,也就是说(X,Y)必然在山上。
保证这 C 个点互不相同。
输出格式
输出只有一个整数 Ans,表示恶梦爬上山顶的路径数对
样例输入输出
walk.in
7 4
6 5
5 3
2 1
7 1
walk.out
34
数据范围
对于 30%的数据,保证 N<=5000
对于另外 20%的数据,保证 C=0
对于另外 20%的数据,保证 C=1
对于 100%的数据,保证 N<=100000,C<=1000
保证对于(0,0),(N,N)不存在障碍点。
Solution
前排Orz跪神犇
来自Philips Weng的题解
我才不会告诉你密码gydg (!有智商!)
Code
#include<cstdio>#include<cstring>#include<algorithm>#define fe first#define se secondusing namespace std;typedef pair<int,int> P;const int MAXM = 1005,MAXN = 200015,Mo = int(1e9) + 7;P Block[MAXM];int Fc[MAXN],Rv[MAXN],F[MAXN],N,C;int Quick(int a,int b){ if (!b) return 1; int mid = Quick(a,b >> 1); if (b & 1) return mid * 1ll * mid % Mo * a % Mo; return mid * 1ll * mid % Mo;}int Getc(int n,int m){ if (m > n) return 0; return Fc[n] * 1ll * Rv[m] % Mo * Rv[n - m] % Mo;}int Normal(int s,int t,int x,int y){ if (x < s || y < t) return 0; return Getc(x + y - s - t,x - s);}int Walk(int s,int t,int x,int y){ return (Normal(s,t,x,y) - Normal(s,t,y - 1,x + 1) + Mo) % Mo;}int main(){ freopen("walk.in","r",stdin),freopen("walk.out","w",stdout); scanf("%d%d", &N, &C); Fc[0] = 1; for(int i = 1;i <= N * 2 + 5;i ++) Fc[i] = Fc[i - 1] * 1ll * i % Mo; Rv[N * 2 + 5] = Quick(Fc[N * 2 + 5], Mo - 2); for(int i = N * 2 + 5;i;i --) Rv[i - 1] = Rv[i] * 1ll * i % Mo; for(int i = 1;i <= C;i ++) scanf("%d%d", &Block[i].fe, &Block[i].se); Block[++ C] = P(N,N); sort(Block + 1,Block + C + 1); for(int i = 1;i <= C;i ++) { F[i] = Walk(0,0,Block[i].fe,Block[i].se); for(int j = 1;j < i;j ++) if (Block[j].se <= Block[i].se) F[i] = (F[i] - F[j] * 1ll * Walk(Block[j].fe,Block[j].se,Block[i].fe,Block[i].se) % Mo + Mo) % Mo; } printf("%d\n", F[C]); return 0;}
End.
- 【NOIP or 省选】登山——数学+DP
- NOIP复习-007——数学方法
- [NOIP 2016] 换教室:数学期望,DP
- CUGB 1032 登山 【DP】
- COJ 1032 登山 DP
- CF 550C 数学 or dp
- 【NOIP or 省选】Melancholy ——线段树+容斥原理
- 动态规划练习——登山
- OpenJudge 1996:登山——题解
- 动态规划练习题—6(登山)
- dp专题 第六题 登山
- [NOIP模拟题][DP][水题][数学][树链剖分][差分序列]
- [NOIP模拟题][数学][乱搞][DP?][扫描线][线段树]
- 【NOIP模板①】经典DP——背包问题
- 玩具装箱(noip冲刺模拟题——DP)
- 《登山》
- 登山
- 登山
- 写一个上下拉动到底时有弹性的listview
- 操作jQuery集合——搜索操作
- php 上传文件
- 算法导论——分治策略
- RabbitMQ基本概念和使用
- 【NOIP or 省选】登山——数学+DP
- github上修改别人的代码并上传
- 如何写好一篇文章
- Codevs 数轴染色
- Android:控件WebView显示网页
- yii2 advanced版本dev和pro配置
- BH&BF&O的区别
- android截屏代码
- iOS9开发--(Content Blocker)Safari广告拦截详解