小数化分数的O(log2n)解法
具体约束:
给定一个小数x,x满足0<=x<1,且保证给定的x保留了18位小数
输出一个分数,使得分母不超过1e9,分子分母互质,且在满足这些条件的情况下最接近x
了解一下法雷数列和stern-brocot tree (某种意义上他们是在描述一个东西)
https://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree
然后考虑在这个树上二分答案的上下界(个人觉得也可以叫伪二分),
一层一层的下降,时间复杂度O(q), q为限制分母大小,本题中为1e9,不行
考虑加速,我们在一次二分过程结束后,上下界由 [l, r] 变为 [l, mid] 或 [mid, r]
但是实际上如果左边界一开始就非常贴近答案,那么我们连续下降很多次的过程中都是将 r 变为 (l + r) / 2
这样是很傻的,所以我们每次考虑下降多次,并且仍然满足条件即可
至于每次下降多少层,就二分一下就可以了
复杂度感觉不太直观,个人感觉是log^2(不负责猜测),不然1w组数据,log的复杂度python不应该2s跑不出
python代码
inf, inff = 10 ** 9, 10 ** 18
for i in range(int(input())):
n = int(input()[2:])
if n == 0: print('0 1')
else:
lp, lq, rp, rq = 0, 1, 1, 1
while max(lq, rq) <= inf:
mp, mq = lp + rp, lq + rq
if mp * inff <= mq * n:
l, r, mid, cnt = 1, (inf - lq) // rq + 1, -1, -1
while l <= r:
mid = l + r >> 1
if (lp + rp * mid) * inff <= (lq + rq * mid) * n:
cnt, l = mid, mid + 1
else:
r = mid - 1
lp, lq = lp + rp * cnt, lq + rq * cnt
else:
l, r, mid, cnt = 1, (inf - rq) // lq + 1, -1, -1
while l <= r:
mid = l + r >> 1
if (rp + lp * mid) * inff > (rq + lq * mid) * n:
cnt, l = mid, mid + 1
else:
r = mid - 1
rp, rq = rp + lp * cnt, rq + lq * cnt
if lq <= inf: print(lp, lq)
else: print(rp, rq)
拓展应用:
问题:给定小数,求出分数p/q,满足p/q>x, q<=1e9,且p/q-x最小
解法:其实是同一个问题,同样是求上下界
问题: 给出abcd四个整数,保证a/b<c/d,求出pq两个整数,使得a/b<p/q<c/d且q最小
解法: 如果abs(ad - bc) == 1,那么a/b和c/d两个分数再某阶法雷序列里是相邻的,就有p=a+c, q=b+d
否则我们很容易有一个O(max(b,d))的做法,从上到下,求出两个分数每层的上下界
需要注意对a/b求的上下界是[l, r), 对c/d求的上下界是(l, r]
然后当某一层a/b的上界==c/d的下界的时候,这个分数就是p/q了
考虑一下这个东西同样是可以加速的,a/b的下界和c/d的上界我们是不关心的,加速方法同上
然后考虑加速a/b的上界r1和c/d的下界l2,我们非常关注他们第一次分开的时候
也就是最早满足r1 <= l2的时候,所以这个也是二分
至此我们就解决了这个问题,时间复杂度和上面是相同的!
小数化分数的O(log2n)解法的更多相关文章
- HDU1717小数化分数2
小数化分数2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 【HDU】1717 小数化分数2 ——计数原理
小数化分数2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- HDU 1717 小数化分数2(最大公约数)
小数化分数2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 紫书 习题8-14 UVa 1616(二分+小数化分数+精度)
参考了https://www.cnblogs.com/dwtfukgv/p/5645446.html (1)直接二分答案.说实话我没有想到, 一开始以为是贪心, 以某种策略能得到最优解. 但是想了很久 ...
- CSU 8月月赛 Decimal 小数化分数
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1303 这个OJ很容易跪所以我贴一下题目 Description 任意一个分数都是有理数,对于任意一 ...
- 杭电oj1717——小数化分数(java实现)
question:小数化分数2 思路: /** * 这道题没有整数部分(有也无所谓,算小数部分,算完了分子分母按倍数加上就好),也就是说数组直接从a[2]开始后面是小数,我把这道题分为了三类: * * ...
- HDU 1717 小数化分数2 数学题
解题报告:输入一个小于1的小数,让你把这个数转化成分数,但注意,输入的数据还有无限循环的小数,循环节用一对括号包含起来. 之前还没有写过小数转分数的题,当然如果没有循环小数的话,应该比较简单,但是这题 ...
- ACM学习历程—HDU1717 小数化分数2(gcd)
Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢? 请你写一个程序不但可以将普通小数 ...
- hdu 1905 小数化分数2
;}
随机推荐
- bzoj1052覆盖问题(二分+贪心)
1052: [HAOI2007]覆盖问题 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2446 Solved: 1131[Submit][Stat ...
- LuoguP3398 仓鼠找sugar
竞赛课想找一道水一点的tarjan题,看看这么久没做题手感有没有掉... 结果这题貌似不是tarjan啊...应该是LCA...假的标签!! 一遍过样例+一遍AC祭(好吧这么水的题也没啥好开心的) 大 ...
- 仓鼠找sugar II
题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a,是任意的)他的基友卧室(b,还是任意的).(注 ...
- 暴力/思维 HDOJ 5386 Cover
题目传送门 /* 题意:给出刷墙的所有的方法,求一种顺序,使得原矩阵刷成目标矩阵 暴力:(题解)我们只要每次找一行或一列颜色除了0都相同的,然后如果有对应的操作,就把这行这列都赋值成0即可 */ /* ...
- 全面学习ORACLE Scheduler特性(6)设置Repeat Interval参数
3.3 设置Repeat Interval Job 和Schedule中REPEAT_INTERVAL参数都是用来控制执行的频率或周期,虽然说周期是一个时间性概念,不过REPEAT_INTERVAL指 ...
- Redis基础---链接管理
Redis连接 Redis AUTH命令是用来向服务器验证给定的密码. 如果密码与在配置文件中的口令相匹配,则服务器会返回OK状态码,并开始接受命令.否则,将返回一个错误,并且客户需要尝试新的密码. ...
- php函数的定义和声明
1.函数的定义 函数是一个被命名的独立的代码段,它执行特定任务,并可以给调用它的程序返回值. 2.函数的优点 提高程序的重用性 提高程序的可维护性 可以提高软件的开发效率 提高软件的可靠性 控制程序的 ...
- anime.js 实战:实现一个带有描边动画效果的复选框
在网页或者是APP的开发中,动画运用得当可以起到锦上添花的作用.正确使用动画,不但可以有助于用户理解交互的作用,还可以大大提高网页应用的魅力和使用体验.并且在现在的网页开发中,动画已经成为了一个设计的 ...
- Android集成微信分享功能应用签名生成方法及分享不生效的问题
通过友盟sdk集成微博.微信.qq等分享功能时,微博和qq很顺利,但在做微信集成时一直不成功.主要问题还是之前在微信开放平台申请创建移动应用时,对应用签名没有填写对,走了很多弯路现总结出来,加深记忆避 ...
- git删除本地分支失败,报错error: branch 'test219' not found.
错误: 删除本地分支报错,操作如下: git branch -d test219 操作失败,错误信息:error: branch 'test219' not found git branch -D t ...