神奇的组合数学——卡特兰数
2017-09-22 21:04
274 查看
卡特兰数:
定义:令h(0)=1,h(1)=1,Catalan数满足递推式。h(n)=h(0)×h(n−1)+h(1)×h(n−2)+...+h(n−1)×h(0)(n≥2)。通项公式:
证明如下(摘自TAOCP的原练习题)(数竞党很少用不严格证明的定理):
解决问题:
1.括号对:合法的括号对对数答案为h(n)。2.二叉树:合法的树有答案为h(n)。
3.分多边形:有h(n) 种分法,用这个可以简单的证明卡特兰数的通项:
不妨设h(i)为i边形的答案,明显,有h(i)=h(n)=h(1)×h(n−1)+h(2)×h(n−2)+...+h(n)h(0)。
又因为我们可以得到,总共的分法有 C(n,n2)个,不合法的是一个“逆序相交”,从而不合法的有:∑C(n−t,t)∗C(t,1)
故相减可得有 所以得证(肯定有人注意到了,这个h(n)的式子与卡特兰数的不符合,实际上这是卡特兰数的另一种递推式)。
例题:
?题?(别笑,题目就叫“题”)
题目:
出个题就好了.这就是出题人没有写题目背景的原因. 你在平面直角坐标系上. 你一开始位于(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为整数} 1.只允许到达x轴非负半轴上的点.即能到达的点集为{(x,y)|x为非负数,y=0} 2.只允许到达坐标轴上的点.即能到达的点集为{(x,y)|x=0或y=0} 3.只允许到达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.
题解:
明显第二个的答案就是h(n),第四个可以看成是两个维度的第二题,所以形式应该是h(n)×h(f(n)),然后待定系数法确定系数,再用数学归纳法证明一下就可以了,结果是Cat(n)∗Cat(n+2)(Cat(x)就是指卡特兰数的第x项)。第一个易推为[C(n,n2)]2,又注意到第三个范围极小,从而dp解决(好吧,好像就没有公式,所以只有1000) ,就是加法原理做啊。代码如下。
代码:
#include<cstdio> #include<algorithm> typedef long long ll; const ll mod = 1000000007; using namespace std; ll q_pow(ll a,ll b) { ll ans = 1; while (b) { if (b%2==1) (ans*=a)%=mod; b/=2; (a*=a)%=mod; } return ans%mod; } ll catalan(ll n) { ll wt = 1 , xiaowt=1; for (ll i = 1;i<=2*n;i++) (wt*=i)%=mod; for (ll i =1; i<=n;i++) (xiaowt*=i)%=mod; ll wtt = q_pow(xiaowt,mod-2); (wtt*=wtt)%=mod; (wtt *= q_pow(n+1,mod-2) )%=mod; return (wt * wtt + mod)%mod; } ll n , typ; int main() { //freopen(".in","r",stdin); //freopen(".out","w",stdout); scanf("%lld%lld",&n,&typ); if (typ == 0) { ll wt = 1; ll xiaowt = 1; for (ll i =1;i<=n;i++) (wt*=i)%=mod; for (ll i =1;i<=n/2;i++) (xiaowt*=i)%=mod; ll wtt = q_pow(xiaowt,mod-2); (wtt*=wtt)%=mod; ll answer = (wt*wtt +mod) %mod; (answer*=answer)%=mod; printf("%lld",answer); } else if (typ==1) { ll asw = catalan(n/2); (asw+=mod)%=mod; printf("%lld",asw); } else if (typ==2)//水水的dp,加法原理 { ll dp[2][2*n+10][2*n+10]; //1 y 0 x dp [0][1][n+2] = 1; dp [1][1][n+2] = 1;//1 dp [0][0][n+1] = 1; dp[1][0][n+1] = 1;//0 dp [0][1] = 1; dp [1][1] = 1;//-1 for (ll i = 1; i <= n;i++) { for (int j = 1 ;j <= 2 * n + 1 ; j++) { dp[0][i][j] = (dp[0][i-1][j+1] + dp [0][i-1][j-1])%mod; dp[1][i][j] = (dp[1][i-1][j+1] + dp [1][i-1][j-1])%mod; } dp[0][i][n+1] = (dp[0][i-1][n + 2] + dp[1][i-1][n + 2] + dp[0][i-1] + dp[1][i-1] )%mod; dp[1][i][n+1] = dp[0][i][n+1]; } printf("%lld\n",dp[0] [n+1]); } else if (typ==3) { ll answ = ( catalan(n/2) * catalan( (n+2)/2 ))%mod; printf("%lld",answ); } return 0; }
结语
这些数学题好啊,以后要多学点。相关文章推荐
- HDU 3240 Counting Binary Trees [卡特兰数] 【数论+组合数学】
- 【组合数学】卡特兰数总结
- 组合数学————卡特兰数
- 组合数学--卡特兰数
- 卡特兰数在多种问题下的应用 组合数学-Catalan数
- [组合数学 卡特兰数] BZOJ 1856 [Scoi2010]字符串
- HDU 3398 String 组合数学+N!质因数分解 卡特兰数
- 组合数学 组合数 卡特兰数 斯特林数
- 51nod 1120 机器人走方格V3(组合数学+卡特兰数+Lucas)
- 【组合数学】卡特兰数
- Move · 卡特兰数 + 组合数学 附逆元
- 【HDU】1131 - Count the Trees(组合数学 - 卡特兰数 & java)
- hdu2067 组合数学 卡特兰数
- HDU 2067 小兔的棋盘 (组合数学 卡特兰数)
- HDU - 4810 Wall Painting(组合数学)
- 区间DP,组合数学(Expression,HDU 5396)
- 【BZOJ4403】序列统计(组合数学,卢卡斯定理)
- 【BZOJ】3997: [TJOI2015]组合数学
- Codeforces 630G Challenge Pennants【组合数学】
- 数学之美番外篇:平凡而又神奇的贝叶斯方法