同余幂的求解算法(原)

2019-04-14 17:10发布

同余幂的求解算法  

1. 问题描述

同余幂,公式表示为bn mod m,即bn次方对m取模。  

2. 算法求解

2.1. 求解方法1

在日常工作中,可能会需要快速的求出同余幂bn mod m,其中bnm都是比较大的整数。例如取b=12345678n=456789,直接计算显然是不可行的,可以把n按二进制展开,则n=456789就变成了1101111100001010101,这样每次只需要求b mod mb2 mod m... b2^(k-1) mod m,然后把对应位置上的二进制是1的项乘起来,每次乘完后求除m的余数即可,大大降低了计算的复杂度。在《离散数学及其应用》里介绍了这种方法,用于密码学中。 伪代码如下: procedure modular exponentiation(b:整数,n=(A(K-1)A(K-2)...A1A0)2(表示2进制展开),m:正整数) x := 1 power := b mod m for i:=0 to k-1 begin         if Ai=1 then x :=(x * power) mod m         power := (power * power) mod m end {x 等于 bn mod m} 下面是C++算法,VC6下通过编译。红 {MOD}部分与参考的代码有出入,一些地方是为了通过编译,一些地方是对代码性能上的优化,请读者留意。 #include #include using namespace std;   int ModularExponentiation(int base, int exp_in_bin, int modular); vector baseBexpansion(int num, short b);   void main(){     //测试,241316进制展开应该是96D     //因为没有修改显示,所以会显示成9613     vector a = baseBexpansion(2413, 16);     //用迭代器显示结果       for(vector::iterator it = a.begin(); it != a.end(); it++){         cout<<*it;     }       cout<     //测试数据,981^937 mod 2537的结果应该是704     int x=ModularExponentiation(981, 937,2537);     cout< }   /**  * 计算 base^exp mod modular这个同余幂的值  * base:底数  * exp_in_bin:指数  * modular:模  * return: 同余幂  */ int ModularExponentiation(int base, int exp, int modular){     //exp进行二进制展开     vector n = baseBexpansion(exp, 2);     int x = 1; //x = base^exp mod modular;       int power = base % modular;     for(int i = n.size() - 1; i > -1 ; i --){         if( n[i] ) { //if n[i] == i             //从二进制展开后的最右端开始求             x = (x * power)% modular;         }         //b^(2^(k-1)) mod m的值         power = (power * power) % modular;     }       return x; }   /**   * 计算数字numb进制展开形式的数组  * num:将被展开的数字  * b:数字展开的基  * return:数字展开后的向量,按照从左往右的顺序存储,如13的二进制展开为1101,存储的顺序也是{1,1,0,1}  */  vector baseBexpansion(int num, short b){     int q = num;     vector a;     while(q != 0){         a.push_back(q % b);         q /= b;     }       //反转a     int size = a.size();     int n = size/2;     int temp = 0;     for(int i = 0; i < n; i ++){         temp = a[i];         a[i] = a[size-1-i];         a[size-1-i] = temp;     }     return a; } 结论:该算法把求bn次幂换成了求某个数的2次幂形式,大大降低了计算的复杂度。  

2.2. 求解方法2

递归求解算法,VC6下已通过编译。 int ModularExponentiation(int b, int n, int m) {     if (n == 0)         return 1;     if (n == 1)         return (b % m);     if (n % 2 > 0) {         return (b * ModularExponentiation(b, n - 1, m)) % m;     } else {         int temp;         temp = ModularExponentiation(b, n / 2, m);         return (temp * temp) % m;     } }  

3. 参考文献

同余幂的原理和C++实现,附赠一个10进制数转换为任意进制的数组的算法.http://blog.csdn.net/cecilulysess/archive/2009/11/12/4801969.aspx 同余幂与康托展开.http://bomb23.blogbus.com/logs/42037791.html