zoj3405 卡特兰数

来源:互联网 发布:惊天破头像软件 编辑:程序博客网 时间:2024/04/28 10:44

Counting Factor Trees

Time Limit: 2 Seconds Memory Limit: 65536 KB

Factoring, i.e., listing all the prime factors, of an integer is a useful skill that often helps to solve math problems. For example, one of the ways to find the GCD (Greatest Common Divisor) or LCM (Least Common Multiple) of two integers is by listing all their prime factors. The GCD is then the product of all the common factors; the LCM is the product of all the remaining ones.

The Factor Tree is a tool for finding such prime factorizations. The figure below demonstrates three factor trees of 108. At the beginning a root with a number is given, sayN, which is to be factored. Then, the root is factored into two childrenN1 and N2 such that N = N1 ×N2 (N1 ≥ 2, N2 ≥ 2). Note thatN1 and N2 need not be prime. The same factoring process continues until all the leaves are prime.

Three factor trees for 108

While the prime factorization is unique, the factor tree reflects the order in which the factors were found, and is by no means unique. So, how many factor trees of a number are there?

Input

There are no more than 10000 cases. A line containing an integer N (2 ≤N ≤ 1000000000) is given for each case.

Output

Print the number of factor trees of N in a line for each case. The answer will be fit in a signed 64-bit integer.

Sample Input

12108642485760

Sample Output

61409637611984000


题意:给一个数n,然后分解它的质因子,再用它的质因子重新组合成树,叶子结点(图片上绿色的部分)都为质因子,问能够组成多少颗不同的树

思路:根据题目可以立马想到n=pi^r1*p2^r2……pm^rm,然后主要要求的是两部分,一部分是叶子从左往右的排列组合方案,第二部分是树的形态。

第一部分:ans1=C(r1,r1)*C(r1+r2,r2)*……C(r1+r2+……rm,rm)。太久没用过排列组合有些生疏了想了很久才明白,如果考虑两个数n个A,m个B,先放A,在m+n个位置中选取n个位置放A,然后B直接放,答案就是C(m+n,n)。而到多的数的时候,不过是利用前面求得的进行递推

第二部分:f(n)=f(1)*f(n-1)+f(2)*f(n-2)……+f(n-1)*f(1),一开始也是不知道这是卡特兰数,找了下卡特兰数的专题看后才知道,等式中f(1)*f(n-1)是总共有n个结点,然后根的左边有1个叶子结点,右边有n-1个叶子结点。其中f(1)=f(2)=1,f(3)=2,f(4)=5,从而推断出等于卡特兰数h(n-1),这里n为结点数。因为这道题本来就要求C(n,m)所以干脆都打好表,h(n)也等于C(2n,n)/(n+1)

因为n范围在一亿以内,因子数最多不超过31个,因为int最多不过2^31,所以卡特兰数求31以内的足够了,C由于要算C(2n,n)所以至少要算到C[62][62]。素数表打个√n就够了,40000差不多,全部弄完跑了30ms,我本来用map记录已找过的结果反而跑了40ms尼玛= =

#include<cstdio>#include<cstring>int prime[40000],tp;bool isprime[40000];long long C[85][85];long long Catalan[45];void init(){memset(isprime,false,sizeof(isprime));memset(C,0,sizeof(C));memset(Catalan,0,sizeof(Catalan));tp=0;for(int i=2;i<=35000;i++){if(!isprime[i]){prime[tp++]=i;for(int j=i+i;j<=35000;j+=i)isprime[j]=true;}}C[0][0]=1;for(int i=1;i<=66;i++){C[i][0]=1;for(int j=1;j<=i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j];}for(int i=0;i<=33;i++)Catalan[i]=C[2*i][i]/(i+1);}long long slove(int n){int sum=0;int cou;int temp=n;long long ans=1;for(int i=0;i<tp&&prime[i]*prime[i]<=n;i++)if(n%prime[i]==0){cou=0;do{n/=prime[i];cou++;}while(n%prime[i]==0);sum+=cou;ans*=C[sum][cou];}if(n!=1)sum++,ans*=C[sum][1];ans*=Catalan[sum-1];return ans;}int main(void){init();int n;while(~scanf("%d",&n)){printf("%lld\n",slove(n));}return 0;}





0 0
原创粉丝点击