【bzoj2852】【vijos1504】强大的区间 题解

题目大意

  给出两个实数 a、b,我们要求一个最小的正整数 k,使得区间 [ak, bk] 是一个包含至少一个整数的区间。
  比如 a=1.2,b=1.3,当 k=4 时,区间为 [4.8, 5.2],包含了整数 5。
  a、b 的整数部分不超过maxlongint,小数部分不超过300位。

二分!?

  显然 k 是既有上界又有下界的,所以第一眼考虑二分。
  然而画一下数轴你就发现,这题没有二分性质。
  具体就不证了,举个栗子就好了:0.45 和 0.55,当 k=2 或 4 时,都合法,但是 k=3 时却不合法。

巧妙的辗转相除思路

  首先,[a, b] 的答案与 [a-1, b-1] 是相同的。因此我们可以先把这个区间变到 a<1 先。   如果此时 b>=1 或者 a=0,那么答案就是1,不然的话就变成了这样解一个不等式:a×k <= t <= b×k,其中 k、t 为正整数。
  把 k 除掉,再取倒数,结果变成这个样子:t/b <= k <= t/a。
  然后我们发现问题变成了求区间 [1/a, 1/b] 的答案,这就迭代下去了。
  综上所述就是:对于每一层,我们有参数 $a$ 和 $b$,先把区间化成 $[a’, b’]$,其中 $a’<1$。若 $b’>=1$ 或者 $a’=0$,则返回 $\lceil a \rceil$,否则处理下一层(参数为 $1/b$ 和 $1/a$)并得到返回值 $t$,然后返回 $\lceil a×t \rceil$。注意,第一层作为最终答案层,返回情况跟别的层有所不同,处理一下。

精度

  据说这题精度不好搞!?
  我觉得首先要把小数化成分数吧,然后往后都用分数计算,这会好算很多。

时间复杂度

  这个过程是典型的辗转相除思想:先用一个数模另一个数,然后交换两个数,重复这一过程。
  所以时间就跟 gcd 一样,都是 log。