1934: ly的二叉树
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 52 Solved: 16
[Submit][Status][Web Board]
Description
某一天,ly正在上数据结构课。老师在讲台上面讲着二叉树,ly在下面发着呆。
突然ly想到一个问题:对于一棵n个无编号节点的有根二叉树,有多少种形态呐?你能告诉她吗?
Input
多组输入,处理到文件结束
每一组输入一行,一个正整数n(1≤n≤1000000),意义如题目所述。
Output
每组数据输出一行,包含一个正整数表示答案,由于数字可能非常大,你只需要把最后的结果对1000000007取模即可。
Sample Input
3
Sample Output
5
HINT
Source
【解析】
这题,很难,很难,很难。
因为。我。没。学过。但是我。会百度。yeah。
首先呢,这个题目是数学问题,人家研究完了,是一个叫卡特兰数的东西。
具体是什么,卡特兰数,看这个,大概能懂什么是卡特兰数,反正这题答案就是这个,为什么,问数学家,看博客。
所以我们现在已知的就是:
以及,递推公式:C(n)=C(n-1)*((4*n-2)/(n+1));
问题是,这题n很大,不可能朴素的打表过。所以就涉及到模的问题。我们知道加减乘都是有取余的法则的(不懂的我也找到了博客取模运算法则及性质),但是这里出现了除法,所以就要学一个新知识(我新学的),逆元,简单解释就是把除法变成乘法运算,然后再取模,但是这个学逆元又要学费马小定理 费马定理推导 。看不太懂也别担心,先会结论然后慢慢磨就好了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1000000007;
const int maxn = 1000010;
ll tab[maxn];
ll quick_pow(ll a, ll b)//快速幂求逆元
{
ll ans = 1;
a %= mod;
while (b)
{
if (b & 1)
ans = ans * a % mod;
b = b >> 1;
a = a * a%mod;
//a*=a%mod;错误
}
return ans;
}
void f()
{
tab[0] = tab[1] = 1;
for (int i = 2; i < maxn; i++)
tab[i] = tab[i - 1] * (4 * i - 2) % mod*quick_pow(i + 1, mod - 2) % mod;
}
int main()
{
int n;
f();
while (~scanf("%d", &n))
printf("%lld\n", tab[n]);
return 0;
}