模重复平方算法
算法原理模重复平方算法是用来快速计算bnmod mb^n \mod mbnmodm的一个算法。考虑直接计算bnmod mb^n \mod mbnmodm,需要n−1n-1n−1次乘法,也就是递归计算bn≡(bn−1mod m)⋅bmod m.b^n \equiv (b^{n-1} \mod m) \cdot b \mod m.bn≡(bn−1modm)⋅bmodm.不过,当nnn很大的时候
算法原理
模重复平方算法是用来快速计算bnmod mb^n \mod mbnmodm的一个算法。
考虑直接计算bnmod mb^n \mod mbnmodm,需要n−1n-1n−1次乘法,也就是递归计算bn≡(bn−1mod m)⋅bmod m.b^n \equiv (b^{n-1} \mod m) \cdot b \mod m.bn≡(bn−1modm)⋅bmodm.不过,当nnn很大的时候,计算会非常耗时。
现在,考虑将nnn的二进制表示n=n0+n12+n222+⋯+nk−12k−1n=n_0+n_12+n_22^2+\cdots +n_{k-1}2^{k-1}n=n0+n12+n222+⋯+nk−12k−1,其中n0,n1,⋯ ,nk−1n_0,n_1,\cdots,n_{k-1}n0,n1,⋯,nk−1为0或者1.
则:
bn≡bn0+n12+n222+⋯+nk−12k−1mod m≡bn0⋅(b2)n1⋅((b2)2)n2⋯(b2k−1)nk−1mod m\begin{aligned} b^n& \equiv b^{n_0+n_12+n_22^2+\cdots +n_{k-1}2^{k-1}} \mod m\\ &\equiv b^{n_0} \cdot (b^2)^{n_1}\cdot ((b^2)^2)^{n_2} \cdots (b^{2^{k-1}})^{n_{k-1}} \mod m \end{aligned}bn≡bn0+n12+n222+⋯+nk−12k−1modm≡bn0⋅(b2)n1⋅((b2)2)n2⋯(b2k−1)nk−1modm
通过观察,我们可以知道,我们需要bbb的偶次幂。设b0=bb_0=bb0=b的话,下一个偶次幂b1=b02mod mb_1=b_0^2 \mod mb1=b02modm,以此类推,b2=b12mod m,⋯ ,bk−1=bk−22mod mb_2=b_1^2 \mod m, \cdots ,b_{k-1}=b_{k-2}^2 \mod mb2=b12modm,⋯,bk−1=bk−22modm,然后代入上面的公式,有:
bn≡b0n0⋅b1n1⋅b2n2⋯bk−1nk−1mod m.b^n \equiv b_0^{n_0} \cdot b_1^{n_1} \cdot b_2^{n_2} \cdots b_{k-1}^{n_{k-1}} \mod m.bn≡b0n0⋅b1n1⋅b2n2⋯bk−1nk−1modm.
又由于n0,n1,⋯ ,nk−1n_0,n_1,\cdots,n_{k-1}n0,n1,⋯,nk−1为0或者1,所以,我们只需要通过不断平方计算出bib_ibi,令初始结果为1,然后,如果nin_ini为1则乘上bimod mb_i \mod mbimodm,否则,不管,继续计算bi+1b_{i+1}bi+1.
可以看出,通过上面的计算,我们只需要最多2[log2n]2[log_2n]2[log2n]次乘法,和一次nnn的分解。
c++实现代码
#include<iostream>
using namespace std;
int msa(int b,int n,int m){
int b1=b;
int res=1;
while(n>0){
if(n%2==1){
res=res*b1%m;
}
b1=b1*b1%m;
n=n/2;
}
return res;
}
int main(){
int b,n,m;
cout<<"Input b:"<<endl;
cin>>b;
cout<<"Input n:"<<endl;
cin>>n;
cout<<"Input m:"<<endl;
cin>>m;
cout<<"The result of b^n mod m is:"<<endl;
cout<<msa(b,n,m)<<endl;
}
gmp函数
在gmp库中,实现了大整数的幂运算,其函数原型如下:
void mpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const mpz_t mod)
rop是返回的结果。
更多推荐



所有评论(0)