This question is actually to investigate the fast power. The so-called fast power is actually the abbreviation of the modulo of the fast power. In short, it is to quickly find the power of a power (modulo). In the process of program design, it is often necessary to find the remainder of a large number for a certain number. In order to obtain a faster algorithm with a larger calculation range, a fast power modulus algorithm is generated.
Let's start with a simple example: seeking .
Algorithm 1. First, design this algorithm directly:
int ans = 1;
for(int i = 1;i<=b;i++)
{
ans = ans * a;
}
ans = ans % c;
The time complexity of this algorithm is reflected in the for loop, which is O ( b ) . There are obvious problems with this algorithm. If a and b are too large, it will easily overflow.
So, let's take a look at the first improvement plan: before talking about this plan, we must first have such a formula:
Everyone should have learned this formula in discrete mathematics or number theory.
So it was improved without thinking:
Algorithm 2 :
int ans = 1;
a = a % c; //加上这一句
for(int i = 1;i<=b;i++)
{
ans = ans * a;
}
ans = ans % c;
Smart readers should be able to think that since a factor is multiplied and then multiplied and the remainder remains unchanged, then the newly calculated ans can also be taken as the remainder, so a better improved version is obtained.
Algorithm 3 :
int ans = 1;
a = a % c; //加上这一句
for(int i = 1;i<=b;i++)
{
ans = (ans * a) % c;//这里再取了一次余
}
ans = ans % c;
This algorithm has no improvement in time complexity, it is still O (b), but it is much better, but under the condition that c is too large, it is still possible to time out, so we introduce the following fast power algorithm.
The fast power algorithm depends on the following obvious formula, which I will not prove.With the above two formulas, we can draw the following conclusions:
Then we can get the following algorithm:
Algorithm 4 :
int ans = 1;
a = a % c;
if(b%2==1)
ans = (ans * a) mod c; //如果是奇数,要多求一步,可以提前算到ans中
k = (a*a) % c; //我们取a2而不是a
for(int i = 1;i<=b/2;i++)
{
ans = (ans * k) % c;
}
ans = ans % c;
We can see that we have changed the time complexity to O (b / 2). Of course, this will not cure the symptoms. But we can see that when we make k = (a * a) mod c , the state has changed, and the final result we require is mod c instead of the original mod c , so we found that this process is possible Iterate. Of course, there will be one more a mod c for odd numbers , so in order to complete the iteration, when b is odd, we make up for the extra one by ans = (ans * a)% c; Part of it can be iterated.
After the iteration as above, when b = 0 , all the factors have been multiplied and the algorithm ends. Then it can be completed in O ( log b ) time. So, there is the final algorithm: fast power algorithm.
Algorithm 5 : Fast power algorithm
int ans = 1;
a = a % c;
while(b>0)
{
if(b % 2 == 1)
ans = (ans * a) % c;
b = b/2;
a = (a * a) % c;
}
The above ideas are transferred from http://www.doc88.com/p-5836182437827.html The following is the program (C ++) that I implemented according to this idea:
class Solution {
public:
bool notZero(vector<int>& b) {
for(int i = b.size()-1; i >= 0; i--) {
if(b[i] > 0) return true;
}
return false;
}
void div(vector<int>& b) {
int tmp = 0;
for(int i = 0; i < b.size(); i++) {
b[i] += tmp*10;
tmp = b[i] % 2;
b[i] = b[i] / 2;
}
}
int superPow(int a, vector<int>& b) {
int ans = 1;
a = a % 1337;
while(notZero(b)) {
if(b[b.size()-1] % 2 != 0) ans = (ans * a) % 1337;
div(b);
a = (a * a) % 1337;
}
return ans;
}
};