372. Super Pow
Medium
Your task is to calculate ab mod 1337 where a is a positive integer and b is an extremely large positive integer given in the form of an array.
Example 1:
Input: a = 2, b = [3]
Output: 8
Example 2:
Input: a = 2, b = [1,0]
Output: 1024
题意
给定一个整数a和一个超长整数b,求a^b模1337的值
思路
首先有一个事实:一个数a的各次幂模k一定会循环
记录最小的b1和b2使得ab1与ab2模1337同余,[b1, b2)之间的数构成一个循环,余数重复出现
下面的问题是求用数组表示的超长整数b对于(b2 - b1)的余数
反复利用性质(a mod k) + (b mod k) = ((a + b) mod k) mod k
和(a mod k) * (b mod k) = ((a * b) mod k) mod k
可以求出这个余数res,然后a^b mod 1337的问题转化为a^res mod 1337的问题,这个余数在之前已经求解过,直接取索引即可
代码
class Solution {
public int superPow(int a, int[] b) {
int n = b.length;
if (n == 0 || (n == 1 && b[0] == 0)) {
return 1;
}
if (n == 1 && b[0] == 1) {
return a % 1337;
}
if (a % 1337 == 0) {
return 0;
}
ArrayList<Integer> mods = new ArrayList<>();
mods.add(1);
a %= 1337;
int res = a, cnt = 1;
int[] index = new int[1337];
Arrays.fill(index, -1);
index[1] = 0;
while (index[res] == -1) {
mods.add(res);
index[res] = cnt++;
res *= a;
res %= 1337;
}
int cnt1 = index[res], cnt2 = cnt;
cnt = cnt2 - cnt1;
if (10 % cnt == 0) {
return b[n-1] <= cnt1? mods.get(b[n-1]): mods.get((b[n-1]-cnt1) % cnt + cnt1);
}
int res10 = 1;
res = 0;
for (int i=n-1; i>=0; --i) {
res = (res + (res10 * b[i])%cnt) % cnt;
res10 *= 10;
res10 %= cnt;
}
return res <= cnt1? mods.get(res): mods.get((res-cnt1) % cnt + cnt1);
}
}