大数幂模运算

大数幂的模运算

题目

  我们知道对于像 7%2,3%5 这样的题,计算机很容易算出它们的结果,但是如果我们需要计算 7123456789%65536 这样的值呢,这时普通的计算方式可能就要花费很久的时间了,有没有简单的方法可以算出来这类大数的模呢?

分析

假设我们有整数a, b与除数m ,那么假设
a % m = j , b % m = t , 有整数 i , s , 使

a=im+jb=sm+t

所以有
ab=(im+j)(sm+t)=ism2+jsm+itm+jt

推出
(ab)modm=(ism2+jsm+itm+jt)modm=jtmodm=((amodm)(bmodm))modm

所以
对于像 7123456789%65536 这样的大数幂模运算,我们可以把大数幂m拆分成形如 m=m1+m2+...+mn 这样的形式,那么 nm=nm1+m2+...+mn=nm1nm2...nmn ,这样通过上面的公式我们就可以很容易算出大数幂了.
因为
abcmodm=((ab)c)modm=(((ab)modm)(cmodm))modm=(((amodm)(bmodm)modm)(cmodm))modm

依次类推既可.

我们再考虑大数幂m要如何分解成形如 m=m1+m2+...+mn 的形式.
观察 211=21+2+8=21×20+1×21+0×22+1×23 .
所以
可以把大数幂m写成二进制,然后只取值为1的位,和这一位在二进制中从右到左的位数(从0开始计算),就可以得到这个大数幂的分解式了.

代码

// m为底数,pow为指数,n为除数
int getMod(int m, int pow, int n)
{
    int x = 1;
    int power = m % n;
    int mask = 1;
    for(int i = 0; i < 32; i++) {
        if((pow & mask) != 0) {
            x = (x * power) % n;
        }
        power = (power * power) % n;
        mask = mask << 1;
    }
    return x;
}

ps

如果计算 ammodp 时发现p是素数而且a与p互质,使用费马小定理可以更快算出结果,因为这时 ap11(modp) 这个可以自己去了解一下.

你可能感兴趣的:(算法)