怎样学习哲学
来源:互联网 发布:java的socket 编辑:程序博客网 时间:2024/05/16 07:46
题目描述
OI大师抖儿在夺得银牌之后,顺利保送pku。这一天,抖儿问长者:“虽然我已经保送了,但是我还要参加学考。马上就要考政治了,请问应该怎样学习哲学,通过政治考试?”
长者回答:“你啊,Too Young Too Simple,Sometimes
Naive!哲学这种东西,不是说想懂就能懂的,需要静心撕烤。你去后面的森林里好好想想。”
长者的后院有一片哲♂学森林。由于一些奥妙重重的原因,这片森林构成了一个n*m的矩形,其中每个点就代表了一棵树。此外,由于辣鸡出题人KJDH从中捣鬼,有些树被连根拔起(也就是消失了)。抖儿每天都要到树下撕烤,因此他想要在每一行选择一棵树。但是他非常讨厌走回头路,因此第i行选择的树必须比第i-1行的靠右。现在抖儿想知道,总共有多少种选择的方案。
输入 第一行三个整数n,m,p,分别表示森林的长、宽,以及消失的树的数目。 接下来p行每行两个整数,表示第ai行第bi列的树消失了。 输出
一行一个整数,表示方案数。由于答案可能很大,请对1000003取模。样例输入
3 5 2 2 3 3 4
样例输出
5
提示
【样例1说明】
方案一:选(1,1)(2,2)(3,3)
方案二:选(1,1)(2,2)(3,5)
方案三:选(1,1)(2,4)(3,5)
方案四:选(1,2)(2,4)(3,5)
方案五:选(1,3)(2,4)(3,5)对于所有的数据,保证n,m≤10^9,p≤min(n*m,2000)
【后记】
在经历了长久的撕烤之后,抖儿终于领悟了哲♂学奥义。
抖儿对长者说:“我知道了!哲学源于生活,只有撕烤生活,才能领悟哲理。”
这题没给部分分(原来是有的,题面里删了,这里不作讨论)
关于100%
- 由题易知,x2>x1,y2>y1,则从(x1,y1)到(x2,y2)的方案数为C(y2-y1-1,x2-x1-1)。
- 要到达终点不经过任何一个空点,不妨设每个空点(包括终点)都是一个关键点,则每种方案都只能到达一个关键点,然后自然推出状态dp[i]为经过关键点i的方案数。
- 但是,起点是第一行任意点,重点是最后一行任意点,可设起点为(0,0),终点为(n+1,m+1)。
- dp[i]的初始状态自然为C(yi-1,xi-1),然后排除经过其它关键点的情况,即减去所有在i左上方的的dp[j]*(关键点j到关键点i的方案数)。
- 最后得dp[i]=C(yi-1,xi-1)-dp[j]*C(yi-yj-1,xi-xj-1),xi>xj,yi>yj
关于C(m,n)
- 可参考Lucas定理,即C(m,n)=C(m%p,n%p)*C(m/p,n/p)
#include<iostream>#include<cstdio>#include<algorithm>#define MOD 1000003using namespace std;int n,m,p;long long dp[2010],ny[1000004],jc[1000004];struct node{ int x,y;} a[2010];bool cmp(node xx,node yy){ return(xx.x<yy.x||(xx.x==yy.x&&xx.y<yy.y));}long long C(int n,int m){ int t=(int)(jc[n]*jc[m-n]%MOD); return jc[m]*ny[t]%MOD;}long long lucas(int x,int y){ if(x>y) return 0; if(x<MOD&&y<MOD) return C(x,y); return lucas(x/MOD,y/MOD)*lucas(x%MOD,y%MOD)%MOD;}long long dfs(int x){ if (dp[x]!=0) return dp[x]; dp[x]=lucas(a[x].x-1,a[x].y-1); for (int i=1;i<x;i++) if (a[i].x<a[x].x&&a[i].y<a[x].y) dp[x]=(dp[x]-(dfs(i)*lucas(a[x].x-a[i].x-1,a[x].y-a[i].y-1))%MOD+MOD)%MOD; return dp[x];}int main(){ scanf("%d%d%d",&n,&m,&p); for (int i=1;i<=p;i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a+1,a+p+1,cmp); jc[0]=jc[1]=1;ny[0]=ny[1]=1; for (int i=2;i<MOD;i++) jc[i]=jc[i-1]*i%MOD,ny[i]=ny[MOD%i]*(MOD-MOD/i)%MOD; a[++p]={n+1,m+1}; for (int i=1;i<=p;i++){ dp[i]=lucas(a[i].x-1,a[i].y-1); for (int j=1;j<i;j++) if (a[j].x<a[i].x&&a[j].y<a[i].y) dp[i]=(dp[i]-dp[j]*lucas(a[i].x-a[j].x-1,a[i].y-a[j].y-1)%MOD+MOD)%MOD; } cout<<dp[p]<<endl; return 0;}
- 怎样学习哲学
- 怎样学习哲学
- 怎样学习哲学
- Unix哲学学习笔记
- 值得学习的处事哲学
- 值得学习的处事哲学
- 值得学习的处事哲学
- 值得学习的处事哲学
- 哲学
- 哲学
- 哲学
- 哲学
- 向狼学习十条处世哲学
- 值得学习的10条处世哲学
- 怎样学习
- 怎样学习
- 各个 Linux 发行版的风格和哲学分别是怎样的?
- 华为30岁了,73岁的任正非管理哲学是怎样迭代的
- mysql--yum安装的路径
- 多个job之间的串并联
- 二项分布的基本概念
- 算法导论第二章之归并排序
- 师门技术论坛:java运行的程序占用哪些资源如何合理使用
- 怎样学习哲学
- MatlabR2015b & VSProfessional2013 混合编码连接以及一个问题(opencv)
- jquery 伴侣
- 获取指定url的扩展名称以及文章ID
- ScrollView 嵌套webview 高度失调 等项关设置,点击拦截
- nodejs logger
- uiNSURLas
- 工作中使用git的实用技巧总结
- windows平台下使用sqlite在unity中创建数据库