1. 程式人生 > 實用技巧 >P1226 【模板】快速冪||取餘運算

P1226 【模板】快速冪||取餘運算

快速冪模板:

int ksm(int b, int p, int k){
    int ans = 1 % k;
    while(p){
        if(p & 1) ans = (long long)ans * b % k;
        b = (long long)b * b % k;
        p >>= 1;
    }
    return ans;
}

思想是將指數p分解為二進位制處理.由於結果數值經常很大,題目一般只要求給出取模後的答案.

而取模具有傳遞性,至少在只進行加減乘運算時,過程中何時取模,取多少次模都不會影響最終答案,前提是過程中不發生溢位.

注意這裡取模物件是int,故取模後一定是int範圍內的數值,但是要注意int與int相乘是會越過int範圍的,需要先進行(long long)強制轉換,取模後範圍變回int再賦值.


具體分析:

將p分解為:

p=a020+a121+a222+a323+...+ak-12k-1,(p轉化為二進位制表示有k位)其中,ai=0或1,

則bp=ba02^0*ba12^1*ba22^2* ... *bak-12^(k-1).所以設ans為1,從最低位開始對p的每一進行處理,若該位為1,則ans乘以左式對應的乘積項.位為0對應的乘積項顯然都變為了1,不需要相乘.

發現在忽略ai的情況下,一個乘積項總是上一個乘積項的兩倍,因此設定一個變數記錄這個以2累乘的過程值便於計算.


複雜度分析:

上述過程的while迴圈進行了log p次,即複雜度為O(log n).這是比一遍遍地累乘原數值要快的(O(p),p為指數).