码迷,mamicode.com
首页 > 其他好文 > 详细

vijosP1388 二叉树数

时间:2015-10-14 10:23:50      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

vijosP1388 二叉树数

 

链接:https://vijos.org/p/1388

 

【思路】

  Catalan数。根据公式h=C(2n,n)/(n+1)计算。首先化简为 (n+i)/i的积(1<=i<=n)

  法一:

高精单精乘除。

  法二:

唯一分解定理。将乘除操作转化为对质因子指数的加减,最后用高精单精乘起来。类于vijosP1137 组合数一题

 

 

【代码1】439ms

 

 

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 struct Bign {
 6     int len;
 7     long long N[10001];
 8     Bign() {
 9         memset(N,0,sizeof(N));
10     }
11 };
12 
13 int n;
14 
15 void multi(Bign& a,int x)
16 {
17     for(int j=0;j<a.len;j++) a.N[j] *= x;
18     int i=0;
19     while(i<a.len || a.N[i]>10) {
20         a.N[i+1] += a.N[i]/10;
21         a.N[i] %= 10;
22         i++;                    //i++
23     }
24     if(a.N[i]) a.len=i+1;  //判断
25     else a.len=i;
26 }
27 
28 void div(Bign& a,int x) {
29     for(int i=a.len-1;i>0;i--) {  //由高位到低位
30         a.N[i-1] += a.N[i]%x*10;
31         a.N[i] /= x;
32     }
33     a.N[0]/=x;  //最后一位
34     while(a.N[a.len-1]==0) a.len--;  //删除前导0
35 }
36 
37 int main() {
38     cin>>n;
39     Bign ans;
40     ans.len=1; ans.N[0]=1;
41     for(int i=1;i<=n;i++) {
42         multi(ans,n+i);
43         div(ans,i);
44     }
45     div(ans,n+1);
46     for(int i=ans.len-1;i>=0;i--) cout<<ans.N[i];
47     return 0; 
48 }

 

 

【代码2】52ms

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<vector>
 4 #include<cmath>
 5 using namespace std;
 6 
 7 const int maxn = 10000+10;
 8 struct Bign{
 9     int len,N[maxn];
10     Bign() {
11         memset(N,0,sizeof(N));
12     }
13 };
14 int e[maxn];
15 int n,m,ans;
16 vector<int> primes;
17 
18 void get_primes(int n) {
19     bool su[maxn]; memset(su,true,sizeof(su));
20     for(int i=2;i<=n;i++) if(su[i]) {
21         primes.push_back(i);
22         if(i<=sqrt(n)) for(int j=i*i;j<=n;j+=i) su[j]=false;
23         //i<=sqrt(n) 否则RE 
24     }
25 }
26 
27 void calc(int x,int d) {
28     for(int i=0;i<primes.size();i++) {
29         while(x%primes[i]==0) {
30             e[i] += d;
31             x /= primes[i];
32         }
33         if(x==1) break;
34     }
35 }
36 
37 void multi(Bign& a,int x)
38 {
39     for(int j=0;j<a.len;j++) a.N[j] *= x;
40     int i=0;
41     while(i<a.len || a.N[i]>10) {
42         a.N[i+1] += a.N[i]/10;
43         a.N[i] %= 10;
44         i++;                    //i++
45     }
46     if(a.N[i]) a.len=i+1;  //判断
47     else a.len=i;
48 }
49 
50 int main() {
51     cin>>n;
52     
53     get_primes(2*n+1);
54     
55     for(int i=1;i<=n;i++) {
56         calc(n+i,1);
57         calc(i,-1);
58     }
59     calc(n+1,-1);
60     Bign ans; ans.len=1; ans.N[0]=1;
61     for(int i=0;i<primes.size();i++){
62         while(e[i]--) multi(ans,primes[i]);
63     }
64     for(int i=ans.len-1;i>=0;i--) cout<<ans.N[i];
65     return 0;
66 }

 

vijosP1388 二叉树数

标签:

原文地址:http://www.cnblogs.com/lidaxin/p/4876480.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!