Stern-Brocot Tree(SB树)

参考资料1
参考资料2
对于二分答案为分数十分管用。
例题:HDU 6209
K 2 3 K^{\frac 23} 的最接近且分母 < = 1 e 5 <=1e5 的分数。
注意这里求的是最接近,所以参考资料1的方法需要做出一些调整。
应该是 [ a , b , c , d ] > [ a + k c , b + k d , c , d ] [a,b,c,d]->[a+kc,b+kd,c,d] 其中这个 k k 是需要二分出来的最大的 k k 满足 a + k c b + k d < = K 2 3 \frac {a+kc}{b+kd}<=K^{\frac 23}
另一个方向类似。
这个方法可以保证如果当前 b + d > = 1 e 5 b+d>=1e5 ,那么 a b \frac ab 是不大于 K 23 \frac K{23} 的最接近, c d \frac cd 是不小于的最接近。
时间复杂度应该是两个 log \log 的。
目前是 H D U \mathrm{HDU} r k 1 rk1
A C   C o d e \mathrm{AC \ Code}

#include<bits/stdc++.h>
#define db long double 
#define LL long long
using namespace std;

int main(){
	int T;scanf("%d",&T);
	for(int K;T--;){
		scanf("%d",&K);
		db x=pow((db)K,(db)2.0/(db)3);
		LL lu=floor(x),ld=1,ru=ceil(x),rd=1;
		for(;ld+rd<=100000;){
			if(lu+ru<x*(ld+rd)){
				int L=1,R=(100000-ld)/rd,m;
				for(;L<R;){
					m=(L+R+1)>>1;
					if(lu+ru*m<x*(ld+rd*m)) L=m;
					else R=m-1;
				}
				lu+=ru*L,ld+=rd*L;
			}
			else{
				int L=1,R=(100000-rd)/ld,m;
				for(;L<R;){
					m=(L+R+1)>>1;
					if(lu*m+ru>=x*(ld*m+rd)) L=m;
					else R=m-1;
				}
				ru+=lu*L,rd+=ld*L;
			}
		}
		if(fabs((db)1.0*lu/ld-x)>fabs((db)1.0*ru/rd-x)) swap(lu,ru),swap(ld,rd);
		printf("%lld/%lld\n",lu,ld);
	}
}
发布了627 篇原创文章 · 获赞 91 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/103956062
sb