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

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. GAN one-shot

    基于one-shot的GAN生成图片 GAN的学习资料用于数据增广GAN的调研: https://zhuanlan.zhihu.com/p/32103958 GAN的各种paper汇集(包括Gener ...

  2. 湖南省第十二届省赛:Parenthesis

    Description Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions. The i-t ...

  3. 2019.9.23JAVA动手动脑

    1请看以下代码,你发现了有什么特殊之处吗? // MethodOverload.java// Using overloaded methods public class MethodOverload ...

  4. spring boot redis session

    1. pom.xml 这里 spring parent的版本 2.1.5会报错 2.1.0和2.1.4经过测试正常 <?xml version="1.0" encoding= ...

  5. jQuery-validate插件初级篇

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  6. a标签点击,页面自动刷新

    <a href="javascript:void(0)" id="reDiagnosis" class="checkBtn"oncli ...

  7. Centos 建一个指定大小的文件夹

    1.使用ramdisklinux可以把一部分内存mount为分区使用,通常为称为ramdisk,分为ramdisk, ramfs, tmpfs.可以一条命令实现我们的需求:mount none tes ...

  8. Vue知识整理11:列表渲染(v-for来实现)

    简单的v-for结构显示迭代数据 通过value别名 显示下面各个属性值 通过index 和key获取同类数组索引,或者不同属性的key属性名

  9. LoadRunner之关联

    一.什么是关联 关联就是将服务器动态返回变化的值保存为一个参数以供后面需要用到的地方使用. 二.什么时候需要关联 1.服务器返回中存在动态变化的值,一般是类似session.token这样的无规则数据 ...

  10. flex 判断对象的类型

    在判断flex对象的类型之前,首先是获取对象类型,获取的方式有: mx.utils.NameUtil.getUnqualifiedClassName(object:Object):String  // ...