坑爹的,,组合数模板,,,
6132 | njczy2010 | 1412 | Accepted | 5572 MS | 50620 KB | C++ | 1844 B | 2014-10-02 21:41:15 |
J - 2-3 Trees
Problem Description
2-3 tree is an elegant data structure invented by John Hopcroft. It is designed to implement the same functionality as the binary search tree. 2-3 tree is an ordered rooted tree with the following properties:
- the root and each internal vertex have either 2 or 3 children;
- the distance from the root to any leaf of the tree is the same.
The only exception is the tree that contains exactly one vertex — in this case the root of the tree is the only vertex, and it is simultaneously a leaf, i.e. has no children. The main idea of the described properties is that the tree with l leaves has the height O(log l). Given the number of leaves l there can be several valid 2-3 trees that have l leaves. For example, the picture below shows the two possible 2-3 trees with exactly 6 leaves.
Given l find the number of different 2-3 trees that have l leaves. Since this number can be quite large, output it modulo r.
Input
Output
Sample Input
6 1000000000 7 1000000000
Sample Output
2 3
题解转自:http://acdream.info/topic?tid=3623
J题:问你一棵有l个叶子的2-3叉树有多少种拓扑结构,结果对r取余。。。 2-3叉树的定义为所有非叶子节点要么有2个儿子,要么有3个儿子,并且所有叶子到根的距离相等。。。 (关于那个O(logn)。。。其实这句话完全是废话,貌似好多人被这句废话给坑到了。。大O只是一个标记,表示渐进的意思,就是说这种树的高度和叶子数n成渐进对数关系)
J题:首先预处理出前2500行的组合数(杨辉三角递推即可,别忘了取余),然后初始化dp[1]=1,若只有根,也有一种情况
然后进行dp,注意到一个性质,2-3树的所有叶子都在同一层,于是就可以通过排列组合来计算叶子的方法数。
于是就转移到了上一层的情况,一层一层记忆化上去,或者递推下来= =。。反正是单组数据~~~
注意用 lld。。。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<map> 9 #include<string> 10 //#include<pair> 11 12 #define N 5005 13 #define M 15 14 #define mod 10000007 15 //#define p 10000007 16 #define mod2 100000000 17 #define ll long long 18 #define LL long long 19 #define maxi(a,b) (a)>(b)? (a) : (b) 20 #define mini(a,b) (a)<(b)? (a) : (b) 21 22 using namespace std; 23 24 ll l,r; 25 ll dp[N]; 26 ll C[N/2][N/2]; 27 28 void ini() 29 { 30 // memset(C,0,sizeof(C)); 31 int i,j; 32 for(i=0; i<=l/2; ++i) 33 { 34 C[i][0] = 1; 35 C[i][i] = 1; 36 for(j=1; j<=l/2; ++j){ 37 C[i][j] = (C[i-1][j] + C[i-1][j-1]) % r; 38 } 39 40 } 41 } 42 43 void solve() 44 { 45 ll i; 46 ll num; 47 ll st; 48 memset(dp,0,sizeof(dp)); 49 dp[0]=0; 50 dp[1]=1; 51 dp[2]=dp[3]=1; 52 for(i=4;i<=l;i++){ 53 st=0; 54 if(i%2==1){ 55 st=1; 56 } 57 for(;3*st<=i;st+=2){ 58 num=st+(i-3*st)/2; 59 dp[i]=(dp[i]+(C[num][st]*dp[num])%r)%r; 60 } 61 } 62 } 63 64 65 void out() 66 { 67 //for(int i=1;i<=l;i++) printf(" i=%d dp=%d ",i,dp[i]); 68 printf("%lld ",dp[l]); 69 } 70 71 int main() 72 { 73 // freopen("data.in","r",stdin); 74 //freopen("data.out","w",stdout); 75 //scanf("%d",&T); 76 // for(int ccnt=1;ccnt<=T;ccnt++) 77 // while(T--) 78 while(scanf("%lld%lld",&l,&r)!=EOF) 79 { 80 //if(n==0 && m==0 ) break; 81 //printf("Case %d: ",ccnt); 82 ini(); 83 solve(); 84 out(); 85 } 86 87 return 0; 88 }