您的位置:首页 > Web前端

LightOJ - 1170 Counting Perfect BST

2017-01-04 21:20 841 查看

题目分析

本题是卡特兰数加逆元,这里面逆元用扩展欧几里得实现。因为事例比较多还需要二分找出一共有多少个值满足。卡特兰数公式是:f[n]=f[n−1]∗(4∗n−2)/(n+1)

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const LL maxn = 1e10+100;
const LL mod = 1e8+7;
vector <LL> vec;
LL ans[(int)1e6];

void exgcd(LL a, LL b, LL& x, LL& y){  //求逆元
if(!b){
x = 1;
y = 0;
}
else{
exgcd(b, a%b, y, x);
y -= x*(a/b);
}
}

void init(){
vec.clear();
for(LL i = 2; i <= 1e5; i++){
LL j = i*i;
while(j < maxn){
vec.push_back(j);
j *= i;
}
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
ans[0] = 0;
ans[1] = 1;
for(LL i = 2; i < 1e6; i++){
LL x, y;
exgcd(i+1, mod, x, y);
ans[i] = ans[i-1]*(4*i-2)%mod*(x%mod+mod)%mod;
}
}

int main(){
init();
int T;
scanf("%d", &T);
LL a, b;
for(int kase = 1; kase <= T; kase++){
scanf("%lld %lld", &a, &b);
int tot = 0;

int l1 = 0, r1 = vec.size()-1;
while(l1 < r1){
int mid = (l1+r1)/2;
if(vec[mid] >= a) r1 = mid;
else l1 = mid+1;
}

if(vec[l2] >= a && vec[l2] <= b && vec[r1] >= a && vec[r1] <= b) printf("Case %d: %lld\n", kase, ans[l2-r1+1]);
else printf("Case %d: 0\n", kase);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: