LightOJ1170 - Counting Perfect BST(卡特兰数)
题目大概就是求一个n个不同的数能构造出几种形态的二叉排序树。
和另一道经典题目n个结点二叉树不同形态的数量一个递推解法,其实这两个问题的解都是是卡特兰数。
- dp[n]表示用n个数的方案数
- 转移就枚举第几个数作为根,然后分成左右两子树,左右两子树的方案数的乘积就是这个数作根的方案数
另外就是题目得先找到[1,1e10]的perfect power,总共102230个;输入的区间[a,b],b-a>=1e6,也就是最多perfect power的个数大概就在a=1,b=1000001范围内,1110个perfect power。
1 #include<cstdio> 2 #include<cstring> 3 #include<set> 4 #include<algorithm> 5 using namespace std; 6 long long pow(long long x,int y){ 7 long long res=1; 8 for(int i=0; i<y; ++i) res*=x; 9 return res; 10 } 11 long long pownum[111111]; 12 int pn; 13 int getCnt(long long a,long long b){ 14 return (upper_bound(pownum,pownum+pn,b)-pownum)-(lower_bound(pownum,pownum+pn,a)-pownum); 15 } 16 long long d[1111]; 17 int main(){ 18 for(long long i=2; i*i<=10000000000L; ++i){ 19 for(int j=2; ; ++j){ 20 if(pow(i,j)>10000000000L) break; 21 pownum[pn++]=pow(i,j); 22 } 23 } 24 sort(pownum,pownum+pn); 25 pn=unique(pownum,pownum+pn)-pownum; 26 d[0]=d[1]=1; 27 for(int i=2; i<1111; ++i){ 28 for(int j=1; j<=i; ++j){ 29 d[i]+=d[j-1]*d[i-j]; 30 d[i]%=100000007; 31 } 32 } 33 d[0]=0; 34 long long a,b; 35 int t; 36 scanf("%d",&t); 37 for(int cse=1; cse<=t; ++cse){ 38 scanf("%lld%lld",&a,&b); 39 printf("Case %d: %lld\n",cse,d[getCnt(a,b)]); 40 } 41 return 0; 42 }