这是一篇嘲讽我之前的自己采用笨重愚蠢思想去解决问题的日志.

RSA 加密与解密涉及到 a ^ b mod c 的问题,如何计算这个值呢? 我会选择 pow(a, b) % c, 事实上在写RSA的时候确实是这么干的,但现在看来真心愚蠢, 因为我为此不得不去实现了一个自己的大数四则运算库,也就是以数组为数(BigNum),而对于mod运算只需要换算为 A % B = A - ( A / B ) * B , 好吧,我自认为轮子准备充分了, 很快就写完了,也觉得很满意,也没什么不合适的地方,但现在开始学DH(Diffie-Hellman)的时候,虽然简单,但是让我学习到了不少取模运算的性质,接着问题就出现了,因为知道了 (a * b) mod c =( (a mod c) * b ) mod c (没错,这就是一条递推式,怎么说呢,这就是构造递归函数的一种条件)

于是我推翻了之前蠢到库的手写大数库,直接写了下面这个递归函数。

unsigned powmod(unsigned a, unsigned b, unsigned c)
{
return (b) ? a * powmod(a, b - 1, c) % c : 1;
}

也就是所谓的 霍纳法则 或者 秦九韶算法, 好吧,怪我先前太蠢,就没想着去mod的性质,给自己留一份记录,好让自己反省反省自己的骄傲自满.

当有了递归函数自然就可以写成非递归,但这里我并不想这么做,因为这问题并没有结束,这问题应该称为求同余幂,于是还有下列这个算法

贴一下人家写的

利用二进制非递归求幂,转载

快速求正整数次幂,当然不能直接死乘。举个例子:

3 ^ 999 = 3 * 3 * 3 * … * 3

直接乘要做998次乘法。但事实上可以这样做,先求出2^k次幂:

3 ^ 2 = 3 * 3

3 ^ 4 = (3 ^ 2) * (3 ^ 2)

3 ^ 8 = (3 ^ 4) * (3 ^ 4)

3 ^ 16 = (3 ^ 8) * (3 ^ 8)

3 ^ 32 = (3 ^ 16) * (3 ^ 16)

3 ^ 64 = (3 ^ 32) * (3 ^ 32)

3 ^ 128 = (3 ^ 64) * (3 ^ 64)

3 ^ 256 = (3 ^ 128) * (3 ^ 128)

3 ^ 512 = (3 ^ 256) * (3 ^ 256)

再相乘:

3 ^ 999

= 3 ^ (512 + 256 + 128 + 64 + 32 + 4 + 2 + 1)

= (3 ^ 512) * (3 ^ 256) * (3 ^ 128) * (3 ^ 64) * (3 ^ 32) * (3 ^ 4) * (3 ^ 2) * 3

这样只要做16次乘法。即使加上一些辅助的存储和运算,也比直接乘高效得多(尤其如果这里底数是成百上千位的大数字的话)。

我们发现,把999转为2进制数:1111100111,其各位就是要乘的数。这提示我们利用求二进制位的算法(其中 mod 是模运算):

于是有如下代码: 根据 (a * b) mod c =( (a mod c) * b ) mod c来进一步分拆大数

// 二进制次幂取模运算
unsigned PowMod(unsigned a, unsigned b, unsigned P)
{
unsigned ans = 1;
while (b) // b将以二进制看待
{
if (b & 1) ans = ans * a % P; // LSB位为 1时确认该位系数不为0则继续相乘
a = a * a % P, b >>= 1; // 乘法结果以 a ^ 2 的形式在积累.
}
return ans;
}

// 重要的事情我只说一遍,根据先前的观察可以归纳出高次幂的多项式是满足用二进制作为次幂的情况下进行拆分, 把 999 转为 2 进制数: 1111100111 ,其个位就是要乘的数。这句话就是重点。

两年后来看,其实就是 蒙哥马利(Montgomery) 性质的算法。

a ^ b mod c 取模运算优化反思(老物)的更多相关文章

  1. HDU——1395 2^x mod n = 1(取模运算法则)

    2^x mod n = 1 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  2. poj 3980 取模运算

    取模运算 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10931   Accepted: 6618 Description ...

  3. java 取模运算% 实则取余 简述 例子 应用在数据库分库分表

    java 取模运算%  实则取余 简述 例子 应用在数据库分库分表 取模运算 求模运算与求余运算不同.“模”是“Mod”的音译,模运算多应用于程序编写中. Mod的含义为求余.模运算在数论和程序设计中 ...

  4. 二分求幂/快速幂取模运算——root(N,k)

    二分求幂 int getMi(int a,int b) { ; ) { //当二进制位k位为1时,需要累乘a的2^k次方,然后用ans保存 == ) { ans *= a; } a *= a; b / ...

  5. PHP中关于取模运算及符号

    执行程序段<?php  echo 8%(-2) ?>,输出结果是: %为取模运算,以上程序将输出0 $a%$b,其结果的正负取决于$a的符号. echo ((-8)%3);     //将 ...

  6. Divide two numbers,两数相除求商,不能用乘法,除法,取模运算

    问题描述:求商,不能用乘法,除法,取模运算. 算法思路:不能用除法,那只能用减法,但是用减法,超时.可以用位移运算,每次除数左移,相当于2倍. public class DividTwoInteger ...

  7. javascript取模运算是怎么算的?其实是取余数

    问到是否整除,这里记录下取模 比如120分钟是不是整点?120%60 === 0 为整点 javascript取模运算是一个表达式的值除以另一个表达式的值,并返回余数. 取模在js里就是取余数的意思. ...

  8. Python中的取模运算

    C++中的取模运算符%只能对整数使用(如果要对浮点数使用需要fmod),Python则不同,对整数或浮点数均有效. 在这里再介绍一下取模的定义:假设a,b两个数,那么a mod b = a - n*b ...

  9. UVALive-7457-Discrete Logarithm Problem(取模运算)

    原题链接 额,一直在理解题意在纠结看不懂,后来才恍然大悟 题意:定义一种新运算 a × b = a * b mod p : 已知条件给定一个p 求 x 这里用到同余与模运算乘法公式:a * b % n ...

随机推荐

  1. C++ -- 类与成员

    一.初始化列表 1.是构造函数中一种成员的初始化方式   例如,class    类名 { 类名(参数列表):成员1(成员1),成员2(成员2)... {   } } 2.用此方法可以解决类中的成员与 ...

  2. UVa 572 Oil Deposits (Floodfill && DFS)

    题意 :输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块.如果两个字符“@”所在的格子相邻(横竖以及对角方向),就是说它们属于同一个八连块. 分析 :可以考虑种子填充深搜的方法.两重for循 ...

  3. RPN

    训练: 特征图是51x39x256,对该图像的每点考虑9个窗口:三种候选面积(128,256,512) x 三种尺度(1:1,1:2,2:1).这些候选窗口称为anchors.如下图: 如果图片尺寸w ...

  4. wannafly 挑战赛9 E 组一组 (差分约束)

    链接:https://www.nowcoder.com/acm/contest/71/E 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 65536K,其他语言131072K Spec ...

  5. (转)WebRTC信令控制与STUN/TURN服务器搭建

    转:https://rtcdeveloper.com/t/topic/13742 本文将向大家介绍两个方面的知识: WebRTC信令控制 STUN/TURN服务器的搭建 在前面的文章中已经向大家介绍了 ...

  6. 当出现no changes added to commit时如何正确使用git提交命令

    对于这个问题,最好的解决方法就是按如下步骤:1.到根目录下:git add .  :("."是必须要的)2.git commit -m "some word"3 ...

  7. @清晰掉 malloc是如何分配内存的?

    任何一个用过或学过C的人对malloc都不会陌生.大家都知道malloc可以分配一段连续的内存空间,并且在不再使用时可以通过free释放掉.但是,许多程序员对malloc背后的事情并不熟悉,许多人甚至 ...

  8. 搜索引擎算法研究专题六:HITS算法

    搜索引擎算法研究专题六:HITS算法 2017年12月19日 ⁄ 搜索技术 ⁄ 共 1240字 ⁄ 字号 小 中 大 ⁄ 评论关闭   HITS(Hyperlink-Induced Topic Sea ...

  9. Python深度学习读书笔记-1.什么是深度学习

    人工智能 什么是人工智能.机器学习与深度学习(见图1-1)?这三者之间有什么关系?

  10. JUnit@Before失效

    在学习Shiro的过程中需要使用到JUnit@Before注解配合测试,但是无论如何,@Before下面的方法都不按照预期的执行,困扰良久,后来各种百度终于找到根源,今分享于诸公,望能解诸公之急: J ...