leetcode Super Pow

题目描述:

   superPow(int a, int[] b),b是一个int数组,每个元素都是正的个位数,组合起来表示一个正整数,例如b=[1,2,3]表示123,求解a^b mod 1337.

思路描述:

   本题的难点是当a和b足够大时会造成溢出,因此应考虑其他算法来实现。

   理论支持(转幂算法):

                  (a^b) mod c = ((a mod c)^b) mod c ----公式1

                  (x*y) mod c = ((x mod c) * (y mod c)) mod c  :积的取余等于取余的积的取余。 -----公式2

   基于上述的算法,有:

          首先将a对c取余,不妨设余数值为x,则:(a^b) mod c = (x^b)mod c    ---基于式1

          (x^b)mod c = (((x ^ (b/2)) mod c) * ((x ^ (b/2)) mod c) ) mod c    :b为偶数

          (x^b)mod c = (((x ^ (b/2)) mod c) * ((x ^ (b/2)) mod c) * x) mod c  :b为奇数

                                                                                                        ----基于式2

   基于上述分析,问题解决思路如下: 首先将a对1337取余;然后将数组组成的整数除2,然后带入superPow(a, b/2),递归进行一直到b为0返回。

   其中b/2实现比较绕,可以考虑我们初学除法时的步骤,实现算法与之很类似。

leetcode上的AC代码:

    

public class Solution {
    public int superPow(int a, int[] b) {
        /*数学公式:
            (a^b) mod c = ((a mod c)^b)
            (x*y) mod c = ((x mod c)*(y mod c)) mod c :积的取余等于取余的积的取余
            
        */
        if(b.length == 0 || isZero(b)){
            return 1;
        }
        
        a = a%1337;
        boolean flag = false;
        if(b[b.length-1]%2 == 1){
            flag = true;  //幂次是奇数
        }
        div(b,2);
        int ans = superPow(a,b);
        ans = (ans*ans)%1337;
        if(flag){
            ans = (ans*a)%1337;
        }
        
        return ans;
        
    }
    
    boolean isZero(int[] num){// 判断数组组成的整数是否为0
        for(int i=num.length-1; i>=0; i--){
            if(num[i]>0){
                return false;
            }
        }
        
        return true;
    }
    
    void div(int[] num, int y){  //完成一次数组组成的整数的除法
        int tmp = 0;
        for(int i=0; i<num.length; i++){
            num[i] += tmp*10;
            tmp = num[i]%y;
            num[i] = num[i]/y;
        }
    }
}
原文地址:https://www.cnblogs.com/bywallance/p/6031506.html