LightOJ - 1170 - Counting Perfect BST (思维+卡特兰数)

1170 - Counting Perfect BST

    PDF (English) Statistics Forum
Time Limit: 2 second(s) Memory Limit: 32 MB

BST is the acronym for Binary Search Tree. A BST is a tree data structure with the following properties.

i)        Each BST contains a root node and the root may have zero, one or two children. Each of the children themselves forms the root of another BST. The two children are classically referred to as left child and right child.

ii)      The left subtree, whose root is the left children of a root, contains all elements with key values less than or equal to that of the root.

iii)    The right subtree, whose root is the right children of a root, contains all elements with key values greater than that of the root.

An integer m is said to be a perfect power if there exists integer x > 1 and y > 1 such that m = xy. First few perfect powers are {4, 8, 9, 16, 25, 27, 32, 36, 49, 64, 81, 100, 121, 125, 128, 144, ...}. Now given two integer a and b we want to construct BST using all perfect powers between a and b, where each perfect power will form the key value of a node.

Now, we can construct several BSTs out of the perfect powers. For example, given a = 1 and b = 10, perfect powers between a and b are 4, 8, 9. Using these we can form the following five BSTs.

4           4         8          9         9

  \          \      / \      /         /

    8          9   4     9   4         8

      \      /                 \      /

       9   8                     8   4

In this problem, given a and b, you will have to determine the total number of BSTs that can be formed using perfect powers between a and b.

Input

Input starts with an integer T (≤ 20000), denoting the number of test cases.

Each case of input contains two integers: a and b (1 ≤ a ≤ b ≤ 1010, b - a ≤ 106) as defined in the problem statement.

Output

For each case, print the case number and the total number of distinct BSTs that can be formed by the perfect powers between a and b. Output the result modulo 100000007.

Sample Input

Output for Sample Input

4

1 4

5 10

1 10

1 3

Case 1: 1

Case 2: 2

Case 3: 5

Case 4: 0

题意:

给你两个数A,B,定义n为[A,B]中所有只有一个质因子且其幂次至少为2的数的个数,求n个不同的数能构造出几种形态的二叉排序树。

思路:

n个不同的数能构造出几种形态的二叉排序树,就是卡特兰数,因此可以O(n)预处理出来。具体的卡特兰数的百度百科上都有。

由于B<=1e10,我们考虑满足条件的数较少,因此可以先暴力找出所有合法的数进行去重排序,然后对于给定的A,B进行二分查找下标即可。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+10;
const ll mo=100000007;  //注意mod
int a[maxn];
ll ans[maxn];
ll prime[maxn],ct;
ll A,B;
void init()
{
	ct=0;
	for(ll i=2;i<=100000;i++)
	{
		ll x=(ll)i*(ll)i;
		while(x<=1e10)
		{
			prime[ct++]=x;
			x*=i;
		}
	}
	sort(prime,prime+ct);
	ct=unique(prime,prime+ct)-prime;
	//cout<<ct<<endl;
}
ll go()
{
	int pos1=upper_bound(prime,prime+ct,B)-prime;
	int pos2=upper_bound(prime,prime+ct,A-1)-prime;
	//cout<<pos1<<" "<<pos2<<endl;
	if(pos1==pos2) return 0;
	return ans[pos1-pos2];
}
ll Pow(ll a, ll b)  //快速幂
{
    ll sum = 1;
    while(b)
    {
        if(b%2)
            sum = sum*a%mo;
        a = a*a%mo;
        b /= 2;
    }
    return sum;
}
int main()
{
	init();
    ll i, now = 1;
    ll T,cas=1,n;
    ans[0]=1;
    for(i=1;i<maxn;i++)
    {
        now = 2*(2*i-1)*now%mo*Pow(i+1, mo-2)%mo;// h(n)=h(n-1)*(4*n-2)/(n+1);
        ans[i]=now;
    }
    scanf("%lld",&T);
    while(T--)
    {
      scanf("%lld%lld",&A,&B);
      printf("Case %lld: %lld\n",cas++,go());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/89071250