大數冪模運算

大數冪的模運算

題目

  我們知道對於像 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) 這個可以自己去了解一下.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章