蒙哥马利幂模算法(二分快速幂)
用于加快幂次取模运算的速度。
形式为这种ab%c 可以等于 (ab1%c)*(ab2%c)%c,其中b=b1+b2;如果b1=b2就更简便一些,(ab/2%c)2%c,只要把数拆成平方的形式就可以使用幂次转二进制的简便运算了。即把x2的幂次转二进制为x10
比如求解某一个值xn%m:513%7首先把n以二进制显示:13(10) = 1101(2) 。定义结果值 r,初始化为1。基值x:n值每次除以2则x就需要加倍。每轮判断n值最末尾位:如果为1,则就表示结果值 r 需要更新改变,也就是 r = r * x%m ;如果为0,则结果值不用更新。
即:51101=51000 * 5100 * 51 ,x就是计算每段的51、5100、51000,r就是计算所有x值乘起来的值。
//c和c++代码
long long my_pow(long long x,long long n,long long m){//x^n%m
long long r =1;//最终求余结果
while(n>0){
if(n&1) {//只要最低位为1就可以更新结果(n&1等价n%2==1)
r = r*x % m;
}
n>>=1;//(等价n/=2)
//不管幂次二进制最低位是否为0都让x加倍,不能else(关键)
x=x*x%m;//只要n往右移都要翻倍
}
return r;
}
//java代码
private static BigInteger my_pow(BigInteger x,BigInteger n,BigInteger m){//x^n%m
//BigInteger类是进行大整数运算使用的类
BigInteger r = new BigInteger("1");//最终求余结果
while(n.compareTo(new BigInteger("0"))==1){
if(n.mod(new BigInteger("2")).compareTo(new BigInteger("1"))==0) {//只要幂次最低位为1就可以更新结果
r = r.multiply(x).mod(m);
}
n = n.divide(new BigInteger("2"));
x = x.multiply(x).mod(m);
}
return r;
}