题(problem)(详解10.5hu测T3:Catalan)
来源:互联网 发布:js获取class对象的值 编辑:程序博客网 时间:2024/06/06 02:55
@liu_runda
【题目描述】
出个题就好了.这就是出题人没有写题目背景的原因.
你在平面直角坐标系上.
你一开始位于(0,0).
每次可以在上/下/左/右四个方向中选一个走一步.
即:从(x,y)走到(x,y+1),(x,y-1),(x-1,y),(x+1,y)四个位置中的其中一个.
允许你走的步数已经确定为n.现在你想走n步之后回到(0,0).但这太简单了.你希望知道有多少种不同的方案能够使你在n步之后回到(0,0).当且仅当两种方案至少有一步走的方向不同,这两种方案被认为是不同的.
答案可能很大所以只需要输出答案对10^9+7取模后的结果.(10^9+7=1000000007,1和7之间有8个0)
这还是太简单了,所以你给能够到达的格点加上了一些限制.一共有三种限制,加上没有限制的情况,一共有四种情况,用0,1,2,3标号:
- 0.没有任何限制,可以到达坐标系上所有的点,即能到达的点集为{(x,y)|x,y为整数}
- 只允许到达x轴非负半轴上的点.即能到达的点集为{(x,y)|x为非负数,y=0}
- 只允许到达坐标轴上的点.即能到达的点集为{(x,y)|x=0或y=0}
- 只允许到达x轴非负半轴上的点,y轴非负半轴上的点以及第1象限的点.即能到达的点集为{(x,y)|x>=0,y>=0}
【输入格式】
一行两个整数(空格隔开)n和typ,分别表示你必须恰好走的步数和限制的种类.typ的含义见【题目描述】.
【输出格式】
一行一个整数ans,表示不同的方案数对10^9+7取模后的结果.
【样例输入0】
100 0
【样例输出0】
383726909
【样例输入1】
100 1
【样例输出1】
265470434
【样例输入2】
100 2
【样例输出2】
376611634
【样例输入3】
100 3
【样例输出3】
627595255
【数据范围】
10%的数据,typ=0,n<=100
10%的数据,typ=0,n<=1000
5%的数据, typ=0,n<=100000
10%的数据,typ=1,n<=100
10%的数据,typ=1,n<=1000
5%的数据, typ=1,n<=100000
10%的数据,typ=2,n<=100
15%的数据,typ=2,n<=1000
10%的数据,typ=3,n<=100
10%的数据,typ=3,n<=1000
5%的数据, typ=3,n<=100000
以上11部分数据没有交集.
100%的数据,保证n为偶数,2<=n<=100000,0<=typ<=3.
分析:
考场上的dp做法详见hu测10.5
正解:
四合一Catalan应用
first.typ=1
裸的Catalan
模拟出入栈
second.typ=0
对于typ=0的数据
枚举横向移动了多少步
横向移动i步时(为了存在合法解,i必须是偶数)
方案数为C(n,i)*C(i,i/2)*C((n-i),(n-i)/2)
横向选择i步移动,i步中有一半正向移动,剩下纵向的n-i步中,一半正向移动
third.typ=2
f[i]表示走了i步回到原点的方案数
(中途可能回到过原点多次)
枚举第一次回到原点时走过的步数j(为了存在合法解,j为偶数)
则此时方案数为f[i-j]*catalan(j/2-1)
解释:
第j步第一次回到远点,之后可能有多次再次回原点(f[i-j]),
在计算这j步时,我们必须保证j步中不回原点,所以catalan(j/2-1)
这个-1就是保证栈不为空
(在我们眼里,移动就像出入栈)
最后答案需要*4
复杂度为O(n^2)所以最大范围只出到1000
fourth.typ=3
枚举横向移动了多少步
横向移动i步时(为了存在合法解,i必须是偶数)
方案数为C(n,i)*catalan(i/2)*catalan((n-i)/2)
选择n步中的i步横向移动,其中一半的步数正向移动,
剩下纵向移动的步数中,也有一半的步数正向移动
Catalan保证是在第一象限内移动(任意前缀入栈不少于出栈)
//这里写代码片#include<cstdio>#include<cstring>#include<iostream>#define ll long longusing namespace std;const ll mod=1000000007;const int N=200010;int n,typ;ll inv[N],jc[N],f[1010]; ll KSM(ll a,int b){ a%=mod; ll t=1; while (b) { if (b&1) t=(t%mod*a%mod)%mod; b>>=1; a=(a%mod*a%mod)%mod; } return t%mod;}void cl(){ jc[0]=1; jc[1]=1; for (int i=2;i<N;i++) jc[i]=(jc[i-1]%mod*(ll)i%mod)%mod; inv[0]=1; inv[1]=1; for (int i=2;i<N;i++) inv[i]=((mod-mod/i)%mod*inv[mod%i]%mod)%mod; for (int i=1;i<N;i++) inv[i]=(inv[i]*(ll)inv[i-1])%mod; //阶乘的逆元 }ll C(int n,int m){ if (n<m) return 0; if (m==0) return 1; return (jc[n]%mod*inv[m]%mod*inv[n-m]%mod)%mod;}ll Catalan(int x) //公式求法 { return C(2*x,x)%mod*KSM((ll)(x+1),mod-2)%mod; //费马小定理求逆元 }int main(){ freopen("problem.in","r",stdin); freopen("problem.out","w",stdout); scanf("%d%d",&n,&typ); cl(); if (typ==1) { printf("%lld",Catalan(n/2)); } else if (typ==0) { ll ans=0; for (int i=0;i<=n;i+=2) //为了能回到原点,枚举的横向步数一定是偶数 ans=(ans+C(n,i)%mod*C(i,i/2)%mod*C(n-i,(n-i)/2)%mod)%mod; printf("%lld",ans%mod); } else if (typ==2) { n/=2; //方便dp f[0]=1; f[1]=4; for (int i=2;i<=n;i++) //枚举总步数 for (int j=1;j<=i;j++) //枚举第一次到达原点的步数 f[i]=(f[i]%mod+f[i-j]%mod*4*Catalan(j-1)%mod)%mod; printf("%lld",f[n]%mod); } else { ll ans=0; for (int i=0;i<=n;i+=2) ans=(ans+C(n,i)%mod*Catalan(i/2)%mod*Catalan((n-i)/2)%mod)%mod; printf("%lld",ans); } return 0;}
- 题(problem)(详解10.5hu测T3:Catalan)
- 校内hu测(10.6T2,T3)(乱搞+贪心+模拟)
- 校内的hu测(10.5)
- randomwalking(10.2hu测)
- HDU---1023-Train Problem II (Catalan数)
- HDU 1023 Train Problem II(Catalan + 大数)
- antipalindrome (10.2hu测)
- Hu矩(转载)
- Hu矩(转载)
- hu
- HDU_1023Train Problem II(关于catalan)
- yveh的hu测(全程表白xiaoyimi)
- 与dalao学校的联hu测zuo(10.26)
- 生哥的hu测
- 一道趣题(catalan数)
- 【NOIP 模拟题】[T3] 约会(lca)
- hdu 1023 Train Problem II 完整高精度模板(以输出大Catalan为例)
- hdu 1023 Train Problem II(catalan 大数)uva 10303 uva 991
- 关于Python读取文件的路径中斜杠问题
- 【Halcon教程3】halcon/c++接口基础 之 构造函数与Halcon算子
- C#解析xml文件获取中国的省市县地区名称和zipcode编号
- mouseenter与mouseover的区别
- Maven_项目搭建启动问题_pom文件依赖出现问题
- 题(problem)(详解10.5hu测T3:Catalan)
- 【Halcon教程4】halcon/c++接口基础 之 析构函数和Halcon算子
- PAT 甲级 1088. Rational Arithmetic (20)
- cartogarpher slam 4
- 数据库水平切分的实现原理解析——分库,分表,主从,集群,负载均衡器(转)
- 【Halcon教程5】 halcon/c++接口基础 之内存管理
- 学习Docker(2017-10-4)
- volatile的详细用法
- 二叉搜索树(Binary Search Tree)