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 }
时间: 2024-11-04 20:00:45

vijosP1388 二叉树数的相关文章

二叉树数

二叉树数 Description 求由n个结点构成的不同的二叉树数.n<=100 每个节点均认为是等价的! Input 输入一个整数n,表示结点数. Output 输出对应的答案. Sample Input 3 Sample Output 5 HINT Source #include <bits/stdc++.h> using namespace std; int f[101][1000]; int tmp[1000]; void mul(int *c,int *a,int *b) {

C 封装一个简单二叉树基库

引文 今天分享一个喜欢佩服的伟人,应该算人类文明极大突破者.收藏过一张纸币类型如下 那我们继续科普一段关于他的简介 '高斯有些孤傲,但令人惊奇的是,他春风得意地度过了中产阶级的一生,而  没有遭受到冷酷现实的打击:这种打击常无情地加诸于每个脱离现实环境生活的  人.或许高斯讲求实效和追求完美的性格,有助于让他抓住生活中的简单现实.  高斯22岁获博士学位,25岁当选圣彼德堡科学院外籍院士,30岁任哥廷根大学数  学教授兼天文台台长.虽说高斯不喜欢浮华荣耀,但在他成名后的五十年间,这  些东西就像

20C-最短路径

#include <bits/stdc++.h> #include <ext/hash_map> #include <ext/hash_set> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/priority_queue.hpp> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/trie_

二叉树基本操作续一:二叉树建立、节点数统计

在上一篇:二叉树基本操作 中,我们描述了二叉树的递归遍历函数.在这里主要是给出这些函数的测试代码,为了测试更加方便,我们实现了三个新的函数:建立二叉树.统计二叉树叶子节点数量.统计二叉树总节点数量.(二叉树的定义用上篇文章中的定义) 二叉树建立: 1 tree_pointer create_bin_tree() 2 { 3 tree_pointer node; 4 int x; 5 scanf("%d", &x); 6 if (x == 0) { 7 node = NULL;

数和二叉树(第七章)

树的基本概念 树的定义 数是有n个节点组成的有限集合(记为T).其中 如果n=0,它是一颗空树,这是树的特例 如果n>0,这n个节点中存在(且仅存在)一个节点作为树的根节点,简称为根:其余节点可分为m(m>=0)个互不交集的有限集T1,T2,Tn,其中每个子集本身又是一颗符合本定义的树,称为根的子树 树的定义是递归的 树是一种非线性结构. 树的逻辑表示方法 树形表示法 文氏图表示方法 凹入表示法 括号表示法 树的基本术语 节点的度与树的度:树中某个节点的子树的个数称为该节点的度.树中各节点的度

【数据结构】二叉树的实现(如:默认成员函数、(叶子)节点数、深度、四种遍历)

二叉树:树的每个节点最多有两个子节点. 我们看下它的结构,有二叉链表结构与三叉链表结构,具体结果如我摘自<C++Primer>中的图. 相比之下,三叉链表的优势在于当我们知道父亲节点要找他的子女节点比较方便和便捷,反之当我们知道子女节点找它的父亲节点时也方便. 下面,我实现下二叉链表的结构. template <class T> struct BinaryTreeNode {     BinaryTreeNode<T>* _left;    //左子树     Bina

二叉树的构造_遍历_求数高和求节点数

1 //手工构造一颗二叉树 ,并给出递归和非递归2类7种遍历方法,树高,节点数求法和逆时针90度显示二叉树 2 //注意本文中2个 typename的使用层次 3 //递归遍历容易溢栈 4 #include <cstdlib> 5 #include <iostream> 6 #include <queue> //用到队列时需要包含此文件 7 #include <stack> //用到栈时需要包含此文件 8 9 using namespace std; 10

二叉树中总分支数与总结点数的关系

对任何一个二叉树,若齐叶子结点数为n0,度为2的结点数为n2,则n0=n2+1.证明如下: 设一颗二叉树上叶子结点数为n0,单分支结点数为n1,双分支结点数为n2,则总结点数为:n0+n1+n2. 而一颗二叉树中,所有结点的分支数(即度数)应等于单分支结点数加上双分支结点数的两倍,即总分支数=n1+2n2. 由于二叉树中除了根结点以外,每个结点都有唯一的一个分支指向它,因此二叉树中:总分支数=总结点数-1. 即n1+2n2=n0+n1+n2-1.即n0=n2+1.

二叉树(8)----求二叉树第K层的节点数和二叉树第K层的叶子节点数,递归方式

1.二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t *m_pElemt; struct BTreeNode_t_ *m_pLeft; struct BTreeNode_t_ *m_pRight; } BTreeNode_t; 2.求二叉树第K层的节点数 (1)递归方式 给定根节点pRoot: 如