超级次方
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;
}
更新 (更好理解方法)
public int myPow(int a, int n) {
int ret = 1;
for (int i = 0; i < n; i++) {
ret = ret * a % 1337;
}
return ret;
}
public int superPow(int a, int[] b) {
a = a % 1337;
int ans = 1;
for (int i = 0; i < b.length; i++) {
ans = (myPow(ans, 10) * myPow(a, b[i])) % 1337;
}
return ans;
}

浙公网安备 33010602011771号