1. 程式人生 > 其它 >超級次方

超級次方

372. 超級次方

你的任務是計算 ab 對 1337 取模,a 是一個正整數,b 是一個非常大的正整數且會以陣列形式給出。

示例 1:
輸入:a = 2, b = [3]
輸出:8

示例 2:
輸入:a = 2, b = [1,0]
輸出:1024

示例 3:
輸入:a = 1, b = [4,3,3,8,5,2]
輸出:1

示例 4:
輸入:a = 2147483647, b = [2,0,0]
輸出:1198

我們都知道

an+m == an + am

(an)m == anm


我們先忽略取模操作看一個例子

比如求 4235 那麼輸入應該是 4 {2 , 3 , 5}

變為求 ((42

)10)10 * (43)10 * 45

先求 res = 42

迴圈 res = res10 * 43 --> 此時 res = (42)10 * 43

迴圈 res = res10 * 45 --> 此時 res = ((42)10 * 43)10 * 45 --> res = ((42)10)10 * ( 43)10 * 45

得到答案 , 退出

總結 : 迴圈--前面得到的值開 10 次方再乘以上後一位的值 , 作為下一次計算的值 , 迴圈到陣列最後一位

加上取模操作方法不變


此時我們可以確保指數冪的位置為個位 ( n <= 9)

但是當底數很大時 , 如果直接使用 Math.pow(a , n) % 1337 或者 Math.pow(a % 1337 , n) % 1337 都會溢位

因為它是直接在 Math.pow(a , n) 或 Math.pow(a % 1337 , n) 就溢位了 , 我們無法在控制在每一步冪次時對數字取模限制其大小

所以要自己定義一個 myPow 遞迴方法


需要降冪 , 否則會出現溢位

那麼我們可以從陣列高位進行計算 , 即先求 ab[0]

上式可以變為 ab[0]/2 * ab[0]/2

但是要考慮 b[0] 奇偶性

  • 偶數時 , ab[0] == ab[0]/2 * ab[0]/2
  • 奇數時 , ab[0] == ab[0]/2 * ab[0]/2 * a

每一步遇到求次方或乘數後要對結果取模 %1337 (題中已給出)

改為以下

  • 偶數時 , ab[0] % 1337 ==( ab[0]/2
    * ab[0]/2 ) % 1337
  • 奇數時 , ab[0] == (( ab[0]/2 * ab[0]/2 ) % 1337 * (a % 1337 )) % 1337

java 程式碼

int base = 1337;
//輔助方法
public int myPow(int a, int n) {
    if (n == 0) {
        return 1;
    }
    //遞迴, 確保每層返回後得到的 halfPow 都是對 1337 取模後的值
    int halfPow = myPow(a, n / 2) % base;
    int ret = (halfPow * halfPow) % base;
    if ((n & 1) == 1) {
        return (ret * (a % base)) % base;
    }
    return ret;
}
//主要方法
public int superPow(int a, int[] b) {
    int ans = 1;
    for (int i = 0; i < b.length; i++) {
        int p = myPow(a, b[i]);
        ans = ((myPow(ans, 10) % base) * (p % base)) % base;
    }
    return ans;
}