1 卡特兰数五大求解方式
- f n = 1 n + 1 C 2 n n f_{n}= \frac{1}{n+1}C_{2n}^{n} fn=n+11C2nn
- f n = C 2 n n − C 2 n n − 1 f_{n}=C_{2n}^{n}-C_{2n}^{n-1} fn=C2nn−C2nn−1
- f n = 1 n + 1 ∑ i = 0 n ( C n i ) 2 f_{n}= \frac{1}{n+1} \sum_{i=0}^{n}{(C_{n}^{i})}^{2} fn=n+11∑i=0n(Cni)2
- f 0 = 1 , f n = 2 ( 2 n − 1 ) n + 1 f n − 1 f_{0}=1,f_{n}= \frac{2(2n-1)}{n+1}f_{n-1} f0=1,fn=n+12(2n−1)fn−1
- f 0 = 1 , f n = ∑ i = 0 n − 1 f n − i − 1 f i f_{0}=1,f_{n}= \sum_{i=0}^{n-1}f_{n-i-1}f_{i} f0=1,fn=∑i=0n−1fn−i−1fi
2 高精度卡特兰数
直接根据
f
n
=
1
n
+
1
C
2
n
n
=
(
2
n
)
!
n
!
(
n
+
1
)
!
f_{n}= \frac{1}{n+1}C_{2n}^{n}= \frac{(2n)!}{n!(n+1)!}
fn=n+11C2nn=n!(n+1)!(2n)!求解高精度卡特兰数。
先用欧拉筛法求出所有的质数,然后对阶乘进行因式分解(勒让德定理),再得出卡特兰数的因式分解,最后根据因式分解求解卡特兰数。
2.1 时间复杂度分析
欧拉筛法的时间复杂度为 O ( n ) \mathcal{O}(n) O(n),因式分解的时间复杂度为 O ( n l o g ( n ) ) \mathcal{O}(nlog(n)) O(nlog(n)),根据因式分解求解卡特兰数的时间复杂度为 O ( n 2 l o g ( n ) ) \mathcal{O}(n^{2}log(n)) O(n2log(n)),所以时间复杂度为 O ( n 2 l o g ( n ) ) \mathcal{O}(n^{2}log(n)) O(n2log(n))。
2.2 实现
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e3+10;
int n,prime[N],cnt,vis[N*2],repeat[N],Catalan_number[N],len;
void multiply(int base_number,int exponent){ //乘上x^sum
while(exponent--){
for(int i=1;i<=len;++i) Catalan_number[i]*=base_number;
for(int i=1;i<=len;++i){
if(Catalan_number[i]>=10){
Catalan_number[i+1]+=Catalan_number[i]/10;
Catalan_number[i]%=10;
if(i+1>len) len++;
}
}
}
}
int FOF(int num,int prime){ //求num的阶乘有多少的prime因数
int sum=0;
while(num) num/=prime,sum+=num;
return sum;
}
int main(){
scanf("%d",&n);
vis[0]=vis[1]=1;
cnt=0;
for(int i=2;i<=2*n;++i){ //筛选出1到2n的质数(欧拉筛法)
if(!vis[i]) prime[++cnt]=i;
for(int j=1;j<=cnt&&prime[j]*i<=2*n;++j){
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
for(int i=1;i<=cnt;++i){ //对卡特兰数分解质因数,因为卡特兰数可以表达为 (2*n)!/ [n!*(n+1)!]
repeat[i]=FOF(2*n,prime[i])-FOF(n,prime[i])-FOF(n+1,prime[i]); //求出有多少个prime[i]因数
}
Catalan_number[1]=1,len=1;
for(int i=1;i<=cnt;++i){ //通过质因数的幂相乘得到卡特兰数
if(repeat[i]){
multiply(prime[i],repeat[i]);
}
}
for(int i=len;i>=1;i--) printf("%d",Catalan_number[i]);
return 0;
}