当前位置:首页 > 每日看点

2的多少次方的最高位是9?

卡卷网12个月前 (05-08)每日看点283

已经有不少回答给出了答案:2 的 53 次方,首位初次出现 9。

我们现在来探究一下此类问题的通法:给定一个底数 2的多少次方的最高位是9?  第1张 和一个前缀 2的多少次方的最高位是9?  第1张,那么使得 2的多少次方的最高位是9?  第1张2的多少次方的最高位是9?  第1张 开头的最小的自然数 2的多少次方的最高位是9?  第1张 是多少?

问题的抽象

我们放到对数域中来研究:一个数 2的多少次方的最高位是9?  第1张 的开头几位是哪些数字,其实蕴含在 2的多少次方的最高位是9?  第1张 的小数部分里面。用 2的多少次方的最高位是9?  第8张 表示 2的多少次方的最高位是9?  第1张 的小数部分,则「2的多少次方的最高位是9?  第1张2的多少次方的最高位是9?  第1张 开头」这个条件,可以表示成: 2的多少次方的最高位是9?  第12张这里面,左右两个端点可以进一步抽象成一个区间 2的多少次方的最高位是9?  第1张,而中间的 2的多少次方的最高位是9?  第14张 可以进一步抽象成 2的多少次方的最高位是9?  第15张,其中 2的多少次方的最高位是9?  第16张 是一个常数。也就是说,我们的问题转化为:给定一个常数 2的多少次方的最高位是9?  第1张 和一个区间 2的多少次方的最高位是9?  第1张,使得 2的多少次方的最高位是9?  第19张 的最小的 2的多少次方的最高位是9?  第1张 是多少?

在原始问题中,各个参数的取值为: 2的多少次方的最高位是9?  第1张

画图观察

我们以编号 2的多少次方的最高位是9?  第1张 为横坐标,2的多少次方的最高位是9?  第23张 为纵坐标,画出 2的多少次方的最高位是9?  第1张 范围内所有的点。其中 2的多少次方的最高位是9?  第25张 的区域用蓝色背景标出,落在此区域内的第一个点的编号就是我们要的答案。

2的多少次方的最高位是9?  第26张

图 1:前 100 个点

可以看到,这些点似乎形成一条条向右下延伸的斜线,这些斜线在纵轴上的截距分别为 2的多少次方的最高位是9?  第1张 。形成这种现象的原因在于 2的多少次方的最高位是9?  第1张。能不能利用这些斜线按图索骥,找到哪些点会落在目标区域里呢?似乎不太行——每条斜线上的点的间距太大了,以至于许多斜线直接「跨过」了目标区域,我们没法预知哪条斜线上会有点落在目标区域里。

我们再多画一些点,把 2的多少次方的最高位是9?  第1张 的点全都画出来:

2的多少次方的最高位是9?  第30张

图 2:前 1000 个点

这回,我们看到了另一种斜线模式:它们向右上延伸,在纵轴上的截距分别为 2的多少次方的最高位是9?  第1张 。形成这种模式的原因在于 2的多少次方的最高位是9?  第1张,其分母为 10。原来那些向右下延伸的斜线其实依然存在,只不过在图 2 的尺度下,它们的点间距太大,导致它们不如向右上延伸的斜线显著。向右上延伸的这些斜线上的点足够密了,以至于随便选取一条斜线,它们都能够在目标区域里留下足迹。我们只需要找起点离目标区域最近的那条斜线(从 0.9 出发的那条),然后找到它落在目标区域里的第一个点即可。

丢番图逼近

我们发现,常数 2的多少次方的最高位是9?  第1张 的每一个分数形式的近似值 2的多少次方的最高位是9?  第1张(例如 2的多少次方的最高位是9?  第1张),都会在某种尺度下形成比较显著的斜线模式。把纵轴看成循环的,则这样的斜线一共有 2的多少次方的最高位是9?  第1张 条。它们与纵轴的交点(下面称为「起点」)的纵坐标都是 2的多少次方的最高位是9?  第1张 的形式,其中 2的多少次方的最高位是9?  第1张 称为斜线的编号。斜线上相邻两个点的编号相差 2的多少次方的最高位是9?  第1张,在纵向的距离是 2的多少次方的最高位是9?  第1张。这个纵向距离可以作为 2的多少次方的最高位是9?  第1张2的多少次方的最高位是9?  第1张逼近误差的一种量度。我们希望找到一个足够好的近似,使得误差不超过目标区间的宽度,即 2的多少次方的最高位是9?  第1张,这样就能保证每条斜线上都有点落在目标区域里。同时,这个近似的分母 2的多少次方的最高位是9?  第1张 也不用太大,够用就行。

丢番图逼近的理论告诉我们,可以把 2的多少次方的最高位是9?  第1张 写成连分数的形式: 2的多少次方的最高位是9?  第1张把这个连分数在任意位置截断,都可以得到 2的多少次方的最高位是9?  第1张 的一个近似值,称为「丢番图逼近」。例如,2的多少次方的最高位是9?  第1张 的前几个丢番图逼近为:2的多少次方的最高位是9?  第1张 。这些丢番图逼近,正是 2的多少次方的最高位是9?  第1张 的「第二类最佳逼近」:按 2的多少次方的最高位是9?  第1张 定义的误差,在所有分母不超过 2的多少次方的最高位是9?  第1张 的分数中是最小的。

顺便提一下,逼近误差还可以定义成 2的多少次方的最高位是9?  第1张。如果一个近似值 2的多少次方的最高位是9?  第1张 使得这种误差在所有分母不超过 2的多少次方的最高位是9?  第1张 的分数中最小,则 2的多少次方的最高位是9?  第1张 称为 2的多少次方的最高位是9?  第1张 的「第一类最佳逼近」。「第二类最佳逼近」是「第一类最佳逼近」的充分非必要条件,也就是说,丢番图逼近只是一部分「第一类最佳逼近」。

我们在所有的「第二类最佳逼近」中,选取第一个满足误差 2的多少次方的最高位是9?  第1张 的近似值。对于 2的多少次方的最高位是9?  第1张 来说,这个近似值是 2的多少次方的最高位是9?  第1张,它的误差约为 2的多少次方的最高位是9?  第1张,小于目标区间的宽度(约为 2的多少次方的最高位是9?  第1张)。

选定了 2的多少次方的最高位是9?  第1张 的一个近似值 2的多少次方的最高位是9?  第1张 后,我们来看看第一个落在目标区域里的点,有希望落在哪些斜线上。起点本来就在目标区域里(即 2的多少次方的最高位是9?  第65张 )的斜线,自然是有戏的。除此之外,若斜线是上升的,那么起点刚好低于目标区域的那条斜线也有戏;若斜线是下降的,那么起点刚好高于目标区域的那条斜线也有戏。我们可以在这些斜线上寻找答案的候补:

  • 对于起点本来就是目标区域里的斜线,我们要找到它上面的第一个点。当然,这个点有可能已经跑到了目标区域之外,所以需要检验。
  • 对于起点刚好在目标区域之外的斜线,我们要找到它上面第一个落在目标区域里的点。为此,我们要首先找到斜线上的第一个点,然后按向量 2的多少次方的最高位是9?  第1张 去推出余下的点的坐标,并算出第一个落在目标区域里的点是谁。

总之,现在我们面临的一个问题是:如何求出 2的多少次方的最高位是9?  第1张 号斜线上第一个点的编号?

裴蜀等式 与 数论倒数

不难发现,2的多少次方的最高位是9?  第1张 号点位于 2的多少次方的最高位是9?  第1张 号斜线上。于是,2的多少次方的最高位是9?  第1张 号斜线上的第一个点的编号,就是使得 2的多少次方的最高位是9?  第1张 的最小的 2的多少次方的最高位是9?  第1张。这个方程也可以写成 2的多少次方的最高位是9?  第1张,称为「裴蜀等式」,其中 2的多少次方的最高位是9?  第1张 是已知数, 2的多少次方的最高位是9?  第1张 是未知数。它的解可以利用扩展欧几里得算法求出。特别地,我们可以先求出 2的多少次方的最高位是9?  第1张 时的解 2的多少次方的最高位是9?  第1张,这样就能很方便地得到 2的多少次方的最高位是9?  第1张 取任意值时的解 2的多少次方的最高位是9?  第1张。这里, 2的多少次方的最高位是9?  第1张 称为 2的多少次方的最高位是9?  第1张 在模 2的多少次方的最高位是9?  第1张 下的数论倒数。

对于 2的多少次方的最高位是9?  第1张 来说,由于 2的多少次方的最高位是9?  第1张,所以 3 在模 10 下的数论倒数为 7。

由于没有任意一条斜线的起点位于目标区域内,而斜线是上升的,所以我们考虑起点刚好低于目标区域的 9 号斜线。它上面的第一个点的编号是 2的多少次方的最高位是9?  第1张,纵坐标是 2的多少次方的最高位是9?  第86张,到目标区域的距离是 2的多少次方的最高位是9?  第1张。在这条斜线上,每往后推一个点,编号增加 10,纵坐标增加 2的多少次方的最高位是9?  第1张。于是,往后推 2的多少次方的最高位是9?  第1张 个点后,就会落在目标区域里,而这个点的编号就是 53。

Show Me the Code

可以把上面的整套流程总结成程序:

import math import sys def cont_frac(x, max_levels=10): """ 求 x 的连分数表示,最多 max_levels 层。 例如:cont_frac(math.log10(2)) = [0, 3, 3, 9, 2, 2, 4, 6, 2, 1]。 """ result = [] while len(result) < max_levels: if abs(x - round(x)) < 1e-9: # 若当前层的值足够接近整数,那就认为是整数 result.append(round(x)) break result.append(int(x)) x = 1 / (x % 1) return result def fold_cont_frac(cont_frac): """ 把连分数化成分数。 例如:fold_cont_frac([0, 3, 3]) = (3, 10),代表 0 + 1 / (3 + 1 / 3) = 3/10。 """ n, d = cont_frac[-1], 1 for a in cont_frac[-2::-1]: n, d = a * n + d, n return n, d def mod_inv(p, q): """ 用扩展欧几里得算法求 p 在模 q 下的数论倒数。 例如:mod_inv(3, 10) = 7。 """ old_r, r = p, q old_s, s = 1, 0 while r != 0: q = old_r // r old_r, r = r, old_r - q * r old_s, s = s, old_s - q * s return old_s def min_power(base, target): """ 求最小的自然数 n,使得 base ** n 以 target 开头。 例如:min_power(2, 3) = 5,因为 2 ** 5 = 32 以 3 开头。 base 可以是任意正实数,target 可以是任意多位正整数。 """ # 求对数域下的目标区间 [s,t) # 因为该区间左闭右开,故将两端均减去一个微小的值, # 以确保与区间端点进行比较时,s 落在区间内,t 落在区间外 c = math.log10(base) % 1 s, t = math.log10(target), math.log10(target + 1) offset = math.floor(s) + 1e-12 s, t = s - offset, t - offset # 求 c 的丢番图逼近,使得误差 err 的绝对值不超过 t - s cf = cont_frac(c) for levels in range(2, len(cf) + 1): p, q = fold_cont_frac(cf[:levels]) err = q * c - p if abs(err) <= t - s: break else: raise ValueError("找不到足够好的丢番图逼近") # 求 p 在模 q 下的数论倒数 n1 n1 = mod_inv(p, q) # 编号从 min_k 至 max_k 的斜线,起点在目标区间内。 # 若这些斜线上的第一个点也在目标区间内,则可作为答案的候补。 min_k, max_k = math.ceil(s * q), math.ceil(t * q) - 1 min_n = float("inf") for k in range(min_k, max_k + 1): n = (n1 * k) % q # 斜线上第一个点的编号 y = (n * c) % 1 # 斜线上第一个点的纵坐标 if s <= y < t and n < min_n: min_n = n # 若斜线向上,则答案也可能在 min_k 下面一条斜线上 if err > 0 and s > 0: k = min_k - 1 n = (n1 * k) % q # 斜线上第一个点的编号 y = (n * c) % 1 # 斜线上第一个点的纵坐标 n += q * math.ceil((s - y) / err) # 目标区域内第一个点的编号 if n < min_n: min_n = n # 若斜线向下,则答案也可能在 max_k 上面一条斜线上 elif err < 0: k = max_k + 1 n = (n1 * k) % q # 由于斜线向下,故对于 0 号点,认为其纵坐标为 1 而非 0 y = (n * c) % 1 or 1 n += q * (math.floor((y - t) / (-err)) + 1) if n < min_n: min_n = n # 返回落在目标区间内的点的最小编号 return min_n

来试验一下,2 的几次方的初次以 1 ~ 9 开头:

>>> for i in range(1, 10): ... n = min_power(2, i) ... print(f"2 ** {n} == {2 ** n}") 2 ** 0 == 1 2 ** 1 == 2 2 ** 5 == 32 2 ** 2 == 4 2 ** 9 == 512 2 ** 6 == 64 2 ** 46 == 70368744177664 2 ** 3 == 8 2 ** 53 == 9007199254740992

果然印证了原题的答案:2的多少次方的最高位是9?  第1张 初次以 9 开头。

还可以试验一下 2 的几次方初次以 10 ~ 99 开头。注意对于 10,程序给出的结果是 2的多少次方的最高位是9?  第1张,因为 1(即 1.0)也可以认为是以 10 开头。20、40、80 同理。

>>> for i in range(10, 100): ... n = min_power(2, i) ... print(f"2 ** {n} == {2 ** n}") 2 ** 0 == 1 2 ** 50 == 1125899906842624 2 ** 7 == 128 2 ** 17 == 131072 2 ** 47 == 140737488355328 2 ** 77 == 151115727451828646838272 2 ** 4 == 16 2 ** 34 == 17179869184 2 ** 54 == 18014398509481984 2 ** 84 == 19342813113834066795298816 2 ** 1 == 2 2 ** 31 == 2147483648 2 ** 51 == 2251799813685248 2 ** 61 == 2305843009213693952 2 ** 81 == 2417851639229258349412352 2 ** 8 == 256 2 ** 18 == 262144 2 ** 38 == 274877906944 2 ** 48 == 281474976710656 2 ** 68 == 295147905179352825856 2 ** 78 == 302231454903657293676544 2 ** 98 == 316912650057057350374175801344 2 ** 5 == 32 2 ** 25 == 33554432 2 ** 35 == 34359738368 2 ** 45 == 35184372088832 2 ** 55 == 36028797018963968 2 ** 75 == 37778931862957161709568 2 ** 85 == 38685626227668133590597632 2 ** 95 == 39614081257132168796771975168 2 ** 2 == 4 2 ** 22 == 4194304 2 ** 32 == 4294967296 2 ** 42 == 4398046511104 2 ** 145 == 44601490397061246283071436545296723011960832 2 ** 52 == 4503599627370496 2 ** 62 == 4611686018427387904 2 ** 72 == 4722366482869645213696 2 ** 82 == 4835703278458516698824704 2 ** 92 == 4951760157141521099596496896 2 ** 102 == 5070602400912917605986812821504 2 ** 9 == 512 2 ** 19 == 524288 2 ** 29 == 536870912 2 ** 39 == 549755813888 2 ** 142 == 5575186299632655785383929568162090376495104 2 ** 49 == 562949953421312 2 ** 59 == 576460752303423488 2 ** 162 == 5846006549323611672814739330865132078623730171904 2 ** 69 == 590295810358705651712 2 ** 79 == 604462909807314587353088 2 ** 89 == 618970019642690137449562112 2 ** 192 == 6277101735386680763835789423207666416102355444464034512896 2 ** 99 == 633825300114114700748351602688 2 ** 6 == 64 2 ** 16 == 65536 2 ** 119 == 664613997892457936451903530140172288 2 ** 26 == 67108864 2 ** 36 == 68719476736 2 ** 139 == 696898287454081973172991196020261297061888 2 ** 46 == 70368744177664 2 ** 149 == 713623846352979940529142984724747568191373312 2 ** 56 == 72057594037927936 2 ** 66 == 73786976294838206464 2 ** 169 == 748288838313422294120286634350736906063837462003712 2 ** 76 == 75557863725914323419136 2 ** 179 == 766247770432944429179173513575154591809369561091801088 2 ** 86 == 77371252455336267181195264 2 ** 189 == 784637716923335095479473677900958302012794430558004314112 2 ** 96 == 79228162514264337593543950336 2 ** 3 == 8 2 ** 13 == 8192 2 ** 209 == 822752278660603021077484591278675252491367932816789931674304512 2 ** 23 == 8388608 2 ** 219 == 842498333348457493583344221469363458551160763204392890034487820288 2 ** 33 == 8589934592 2 ** 229 == 862718293348820473429344482784628181556388621521298319395315527974912 2 ** 43 == 8796093022208 2 ** 239 == 883423532389192164791648750371459257913741948437809479060803100646309888 2 ** 146 == 89202980794122492566142873090593446023921664 2 ** 53 == 9007199254740992 2 ** 156 == 91343852333181432387730302044767688728495783936 2 ** 63 == 9223372036854775808 2 ** 166 == 93536104789177786765035829293842113257979682750464 2 ** 73 == 9444732965739290427392 2 ** 176 == 95780971304118053647396689196894323976171195136475136 2 ** 83 == 9671406556917033397649408 2 ** 279 == 971334446112864535459730953411759453321203419526069760625906204869452142602604249088 2 ** 186 == 98079714615416886934934209737619787751599303819750539264 2 ** 93 == 9903520314283042199192993792

可以看到,输出的前半段像一棵圣诞树一样错落有致,每一个三角形中,指数的个位数都相同,十位数基本上是依次递增,偶尔会跳过一个数。这背后的原因,就在于 2的多少次方的最高位是9?  第1张 非常接近 10 的整数次幂。在输出的后半段,「指数依次加 10」的模式开始显出一些漏洞,被 2的多少次方的最高位是9?  第1张 等指数更大的幂填充;到了最后,漏洞多到填充它们的幂的指数也显示出了「依次加 10」的规律(例如 2的多少次方的最高位是9?  第1张2的多少次方的最高位是9?  第1张)。

还可以换一些数字来玩:

>>> min_power(math.pi, 520) 275 >>> min_power(666, 888) 2000 >>> min_power(114514, 1919810) 1947860

可以验证,确实有:

2的多少次方的最高位是9?  第96张

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2025/05/12985.html

分享给朋友:

相关文章

Photoshop 有哪些使用技巧?

Photoshop 有哪些使用技巧?

不看后悔系列!本篇分享25个PS实用的技巧! 不能保证每个都能让你惊艳,但是却是我用心写出来的,希望对你有帮助。 另外我的知乎也写了接近200篇PS的技巧,超级合集分享! 分享25个关于PS的技巧 一、快速制作文字倒影1、新建文档,15…

你捡过最大的漏是什么?

你捡过最大的漏是什么?

买了套二手房,软磨硬泡便宜了1个w 结果就是一屋子狼藉 原业主说反正你们要重新装修 就不收拾了 等完了你们一起收拾掉吧 落了很多柜子 电器是啥的 今天打开卧室柜子一看… 现在是去存钱的路上 有朋友知道这样存钱银行会给发大米跟油吗…

为什么说不懂电脑的不要碰AMD?

作为一个资深垃圾佬,说缺点前,先说优点吧AMD CPU(后续简称AU)的优点:处理器对比Intel,三级缓存更大,最明显的感知就是,网游帧数更高(5900X,7900X之类高端型号都是双CCX共享大缓存,反而不如次一点的CPU帧数更高);相…

下一个风口最可能是什么?

下一个风口最可能是什么?

肯定是一带一路了,国内没什么卷的空间了,现在国家正在给一带一路的第三世界国家建设基础设施,等交通打通之后,就是通信打通,通信打通就是贸易打通,未来我建议大家重仓小语种,阿拉伯语最值得学(也有其他小语种自己去查一带一路国家),将来去其他国家随…

只有我一个人后悔升级鸿蒙next吗?

只有我一个人后悔升级鸿蒙next吗?

我有一台mate 60 pro,第一时间升级了“纯血鸿蒙”。 虽然功能并不完善,甚至有些简陋,但是我非常~非常不后悔升级鸿蒙next系统。 因为.... 这就是一款“大型养成系游戏“,给我平淡的生活提供了源源不断的情绪价值。 我每天特别…

什么样的网站能快速捕获你的心?

什么样的网站能快速捕获你的心?

大家好,我是程序员鱼皮。 大家如果平时使用网站或产品时出现了问题,一般都会去寻找 “联系客服” 的位置,从而获得人工的帮助。我们团队的面试刷题产品 - 面试鸭最近就遇到了这样一个难题:明明我们网站右下角就有联系客服按钮、而且我们每道面试题目…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。