題目:模冪運算-要求演算法返回冪運算a^b的計算結果與1337取模後的結果
其中b是一個非常大的數,所以b使用陣列形式表示。即無法直接a^b%1337計算
此類問題的關鍵需要分治,拆分成更小規模的計算
1)對於a^b,如果b=1234,則a^1234 = a^4 *(a^123)^10
即a^b可以拆分後遞迴運算
2)對於取模運算,(a*b)%k= (a%k)*(b%k)%k
證明a=Ak +B,b=Ck+D
則a*b = ACk^2+ADk+BCk+BD
則a*b%k= BD%k=(a%k)*(b%k)%k
所以上述問題,a^1234方如果數值比較大,則可以a%k * a^1233 ,遞迴算出所有的
所以演算法為
/** * a的【1,2,3】冪次方取餘數1337,計算 其中【1,2,3】可以無限大 */ public class Power { /** * a的【1,2,3】冪次方取餘數1337,計算 其中【1,2,3】可以無限大 * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>(); blockingDeque.add(1); blockingDeque.add(2); blockingDeque.add(3); int a = 2; //1) a^[1,2,3] = a^3 * (a^[1,2])^10 //2) a*b%c = (a%c)*(b%c)%c int i = superPower(a, blockingDeque); System.out.println(i); } public static int superPower(int a, BlockingDeque<Integer> blockingDeque) throws InterruptedException { if(blockingDeque.isEmpty()){ return 1; } int last = blockingDeque.takeLast(); int base = 1337; int part1 = myPower(a,last,base); int part2 = myPower(superPower(a,blockingDeque),10,base); return (part1*part2)%base; } public static int myPower(int a,int k,int base){ a = a % base; int res = 1; for(int i=0;i<k;i++){ res = res * a; res = res % base; } return res; }
3)冪運算仍可以進一步最佳化
即a^b = a * a^b-1 b為奇數, = (a^(b/2))^2
則可以進一步最佳化為
import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; /** * a的【1,2,3】冪次方取餘數1337,計算 其中【1,2,3】可以無限大 */ public class Power2 { /** * a的【1,2,3】冪次方取餘數1337,計算 其中【1,2,3】可以無限大 * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>(); blockingDeque.add(1); blockingDeque.add(2); blockingDeque.add(3); int a = 2; //1) a^[1,2,3] = a^3 * (a^[1,2])^10 //2) a*b%c = (a%c)*(b%c)%c // 3) a^k = // // 3.1) (a^[k/2])^2 // // 3.2) a * a^[k-1] int i = superPower2(a, blockingDeque); System.out.println(i); Double res = Math.pow(a,123)%1337; String s = String.valueOf(res); System.out.println(s.substring(0,s.length()-2)); } public static int superPower2(int a, BlockingDeque<Integer> blockingDeque) throws InterruptedException { if(blockingDeque.isEmpty()){ return 1; } int last = blockingDeque.takeLast(); int base = 1337; int part1 = myPower2(a,last,base); int part2 = myPower2(superPower2(a,blockingDeque),10,base); return (part1*part2)%base; } public static int myPower2(int a,int k,int base){ if(k==0){ return 1; } a = a % base; if(1 == k%2){ return (a*myPower2(a,k-1,base))%base; }else{ int res = myPower2(a, k / 2, base); return (res*res)%base; } } }