关于-密码学算法中-类似-编程函数pow(3, 13, 7)的计算-快速幂算法结合模运算(Exponentiation by Squaring with Modular Reduction)
Posted on 2026-06-05 17:00 520_1351 阅读(10) 评论(0) 收藏 举报而 pow(g, a, p) 之所以能“秒算”,是因为它在底层使用了高度优化的快速幂算法结合模运算(Exponentiation by Squaring with Modular Reduction)。
它的精妙之处在于“边算边约减”——在每一次平方或乘法运算后,立刻对中间结果进行取模操作。这样,整个计算过程中的所有中间变量都被死死地控制在
p 的范围之内,彻底避免了产生巨大中间值的问题。
这里举例说明 pow(3, 13, 7) ,即表示 计算 3^13 % 7 的结果 , 其核心是要将 3^13 分解成多个数的乘积 , 计算机中,最快最简单的就是3不变, 将指数13进行分解
如果按照你直觉中的“先算出完整结果再取模”,我们需要先算 3^13 ,这等于 1594323,然后再用 1594323 除以 7 求余数。如果指数更大,这个数字会大到计算机直接爆内存。
而快速幂算法的“边算边约减”和“二进制分解”是这样操作的:
首先,我们将指数 13 写成二进制:1101 , 在二进制中,每一位代表一个权重:
第 0 位是 1 - 代表 2^0 = 1 第 1 位是 0 - 代表 2^1 = 2 第 2 位是 1 - 代表 2^2 = 4 第 3 位是 1 - 代表 2^3 = 8
所以,13=8+4+1,而且可以观察出来,二进制中,低位的1如果为x ,它旁边高位的1就代表是x的2倍,即2x了
这样,我们带入底数3 , 也即如果 3^x 的下一个高位如果是1 , 就是 3^(2x) , 也即是 (3^x)^2 , 也即低高位都是1 , 位数的3^x 的 平方 就是下一个高位的结果
那么数学上,3^13 就可以拆解为:3^8 * 3^4 * 3^1 = 3^(8+4+1)
第二步:开始迭代计算(核心过程)
我们准备两个变量:结果(res) = 1,底数(base) = 3。我们从二进制的最低位(最右边)开始往左看:
【第 1 轮】处理二进制的最后一位(1)
- 判断:当前位是 1,说明这个 3^1 需要被乘进最终结果里。
- 更新结果:res = res × base % 7 → 1 × 3 % 7 = 3。
- 底数自乘取模:不管这一位是不是1,底数都要平方,为下一位做准备。base = 3 × 3 % 7 = 9 % 7 = 2。(注意!这里立刻取了模,把 9 变成了 2,数值非常小)。【这也代表下一个高位3^高位1位置的结果 % 7 = 2】
- 移动:向右移一位,处理下一个二进制位。
【第 2 轮】处理二进制的倒数第二位(0)
- 判断:当前位是 0,说明不需要乘入结果,跳过。
- 底数自乘:base = 2 × 2 % 7 = 4。(同样立刻取模,保持数值很小)。
- 移动:继续右移。
- 判断:当前位是 1,需要乘入结果。此时的
base已经通过连续平方代表了 3^4 。 - 更新结果:
res = res × base % 7→3 × 4 % 7 = 12 % 7 = 5 - 底数自乘:
base = 4 × 4 % 7 = 16 % 7 = 2。(再次取模)。 - 移动:继续右移。
- 判断:当前位是 1,需要乘入结果。此时的
base代表了 3^8 。 - 更新结果:
res = res × base % 7→5 × 2 % 7 = 10 % 7 = 3。 - 底数自乘:
base = 2 × 2 % 7 = 4。 - 移动:右移后没有更多位数了,结束。
所以最后的结果就是3 , 这里我们总结一下:
% 7 这就是为什么 Python 的 pow(g, a, p) 能够“秒算”:它利用二进制把巨大的指数拆解成了少量的平方和乘法操作
时间复杂度从 O(a)降到了 O(log a) 并且死死地把所有中间数字控制在模数 p 的范围内,彻底避免了内存爆炸。
尊重别人的劳动成果 转载请务必注明出处:https://www.cnblogs.com/5201351/p/20331011
作者:一名卑微的IT民工
出处:https://www.cnblogs.com/5201351
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
由于博主的水平不高,文章没有高度、深度和广度,只是凑字数,不足和错误之处在所难免,希望大家能够批评指出。
博主是利用读书、参考、引用、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个卑微的IT民工!
浙公网安备 33010602011771号