lightoj 1170 Counting Perfect BST
来源:互联网 发布:手机如何装修淘宝店铺 编辑:程序博客网 时间:2024/04/30 02:20
perfect power 是指可以表示成x^y(x>1,y>1)的数,给一个区间[A,B]求由这个区间的所有perfect能组成多少种不同形态的二叉查找树。
比如要查找T中在区间[A,B]内的数的个数,那么结果就是lower(B)-lower(A-1);
预处理出范围内的所有perfect power和范围内的所有卡特兰数。二分搜索个数。
注意到x和y都是大于1的。而题目的范围是10^10,那么只要枚举x到10^5多一点即可。
然后算了一下每个数之多只要算30次左右就行了。如此来看,暴力是完全可以选出所有的perfect power的。
对这些数排序,然后二分搜索区间AB的上下界即可。
一、在看别人代码的时候看到一个非常屌的二分。
int lower(ll x) { if(x<T[0])return 0; if(x>=T[T.size()-1])return T.size(); int l=0,r=T.size()-1; int mid; while(l<=r) { mid=(l+r)>>1; if(T[mid]==x)return mid+1; if(x>T[mid])l=mid+1; else r=mid-1; } return min(r,mid)+1;}
比如要查找T中在区间[A,B]内的数的个数,那么结果就是lower(B)-lower(A-1);
二、卡特兰数。
Ci=(4*i-2)/(i+1)*Ci-1
这个题用到的卡特兰数大约有十万,要求的是卡特兰数mod1000000007(质数)。
求的时候直接模肯定是不行的,得要求逆元。
三、乘法逆元
乘法逆元。一个数a,如果存在一个数n使得a×n=1( mod p)。那么称n为a对p的乘法逆元。
存在乘法逆元的必要条件是gcd(a,p)=1;
两种简单求法。
1、由费马小定理知,n=a ^ (euler(p))-1,euler是欧拉函数值。特殊的,素数p的欧拉函数值是p-1;
2、同余,上述式子相当于求a×n+p×y=1中的n的值。用扩展欧几里得即可求得,如果结果小于0,一直加p直到为正为止。
到这里,这个题算是做完了。快速幂什么的就不提了。
#define mod 100000007const ll maxT=11000000000LL;ll PowMod(ll a,ll n){ if(n==1)return a; if(n==0)return 1; ll tmp=PowMod(a,n>>1)%mod; tmp=(tmp*tmp)%mod; if(n&1)tmp=(tmp*a)%mod; return tmp;}vector<ll> sel;void ini2(){ sel.clear(); for(ll i=2;i<maxn;i++){ ll tmp=i*i; if(tmp>maxT)break; while(tmp<=maxT){ sel.pb(tmp); tmp*=i; } } sort(sel.begin(),sel.end()); sel.erase(unique(sel.begin(),sel.end()),sel.end());}int upper(ll x){ int l=0,r=sel.size()-1; int mid; while(l<r){ mid=(l+r)>>1; if(sel[mid]>x)r=mid; else l=mid+1; } return r;}int lower(ll x){ int l=0,r=sel.size()-1; int mid; while(l<r){ mid=(l+r)>>1; if(sel[mid]>=x)r=mid; else l=mid+1; } return r;}ll exgcd(ll a,ll b,ll &x,ll &y){ if(b==0){ x=1,y=0;return a; } ll gcd=exgcd(b,a%b,x,y); ll temp=x;x=y; y=temp-(a/b)*y; return gcd;}ll C[110000];int main(){ //cout<<PowMod(3,mod)<<endl; ini2(); memset(C,0,sizeof(C)); C[0]=0; C[1]=1; for(ll i=2;i<109000;i++){ ll x,y; exgcd(i+1,mod,x,y); C[i]=(((C[i-1]%mod)*((4*i-2)%mod))%mod*(x%mod+mod)%mod)%mod; } int T; scanf("%d",&T); for(int tt=1;tt<=T;tt++){ ll a,b; scanf("%lld%lld",&a,&b); int tmpa=lower(a); int tmpb=upper(b); ll ans=C[tmpb-tmpa]; printf("Case %d: %lld\n",tt,ans); } return 0;}
0 0
- lightoj 1170 Counting Perfect BST
- LightOJ - 1170 Counting Perfect BST
- lightoj 1170 - Counting Perfect BST 数学+DP
- Light OJ 1170 Counting Perfect BST (DP+数学)
- 【LightOJ - 1058】Parallelogram Counting
- lightoj-1058 - Parallelogram Counting
- LightOJ 1058 - Parallelogram Counting
- Lightoj 1307 Counting Triangles
- LightOJ-1058 Parallelogram Counting
- [UVALive5058] Counting BST && 计数DP + BST
- Counting Nodes in a BST
- lightoj 1148 - Mad Counting 【数学】
- lightOJ 1148 - Mad Counting 【水题】
- LightOJ 1148 - Mad Counting【数学】
- LIGHTOJ-1148 - Mad Counting(规律)
- lightoj-1307-Counting Triangles【思维】
- 1115. Counting Nodes in a BST (30)[bst+dfs遍历]
- LightOJ - 1201 A Perfect Murder(树形DP)
- 【归并排序】求逆序对的时候顺手写的,于是就顺手贴了,于是标题就长了
- Lua语言学习之错误与异常
- uva1160X-Plosives并查集
- 星星
- hdu2444 The Accomodation of Students
- lightoj 1170 Counting Perfect BST
- 函数 形参和实参
- Java中的设计模式,书籍推荐
- UITableViewCell重用机制
- 外包公司框架搭建需要注意的几点
- 浮躁病
- CentOS下使用RPM安装MySQL出现file ... conflicts with file ...提示后没有反应的解决方法。
- 分糖果
- 为什么理想电流源的等效内阻是无限大