[LintCode] Fast Power

Posted Push your limit!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LintCode] Fast Power相关的知识,希望对你有一定的参考价值。

Calculate the (a^n) % b where a, b and n are all 32bit integers.

 

Example

For 231 % 3 = 2

For 1001000 % 1000 = 0

 

 A straightforward solution is to multiply a by itself n - 1 times, then modularize the result by b. It takes O(n) runtime if we 

consider each single arithmetic opertaion O(1) operation.

 

A better approach is to use a divide and conquer method:

x^n = x^(n/2) * x^(n/2), if n is even;

x^n = x^(n/2) * x^(n/2) * x, if n is odd;

 

T(n) = T(n/2) + O(1).  O(logn) runtime

 

The following implementation uses this log algorithm. However,  it does not work correctly when n gets big.

Since a, b, n are all 32 bits integers, so n can get really big, thus x^n become humongous, even a double type can‘t 

contain all bits. In this case, x^n will be truncated to a 32 bit integer, causing incorrect result.

 1 public class Solution {
 2     public int fastPower(int a, int b, int n) {
 3         if(n == 0) {
 4             return 1 % b;
 5         }
 6         if(n == 1) {
 7             return a % b;
 8         }
 9         return (int)(power(a, n) % b);
10     }
11     private double power(int x, int n) {
12         if(n == 0) {
13             return 1;
14         }
15         double half = power(x, n / 2);
16         if(n % 2 == 0) {
17             return half * half;
18         }
19         return half * half * x;
20     }
21 }

 

To fix the overflow issue, we need to modular arithmetic distributive property: (x*y) % N = ((x % N) * (y % N)) % N.

Apply the % b operation when calculating the intermediate result. Because b is an integer, any number that gets % b

is going to be inside an integer range.

The following implementation shows this fix.

However, it still has a hidden bug at lines 11 and 13.

At line 10, each returned "product" is within integer range now, but when multiplying two integers that can be big, 

it is possible that this multiplication overflows. Thus we need to declare the return type as long, so it gives room

for possible overflow multiplication. The intermediate multiplications are modularized by b, ensuring the result within

integer range. So we can safely convert from long to int.

 1 class Solution {
 2     public int fastPower(int a, int b, int n) {
 3         if (n == 1) {
 4             return a % b;
 5         }
 6         if (n == 0) {
 7             return 1 % b;
 8         }
 9         
10         int product = fastPower(a, b, n / 2);
11         product = (product * product) % b;
12         if (n % 2 == 1) {
13             product = (product * a) % b;
14         }
15         return (int) product;
16     }
17 }

 

 

 1 class Solution {
 2     public int fastPower(int a, int b, int n) {
 3         if (n == 1) {
 4             return a % b;
 5         }
 6         if (n == 0) {
 7             return 1 % b;
 8         }
 9         
10         long product = fastPower(a, b, n / 2);
11         product = (product * product) % b;
12         if (n % 2 == 1) {
13             product = (product * a) % b;
14         }
15         return (int) product;
16     }
17 }

 

 

Modular arithmetic properties 

Associativity: (x + (y + z)) % N = ((x + y) % N + z % N) % N;

Commutativity: (x * y) % N = ((x % N) * (y % N)) % N; 

Distributivity: (x * (y + z)) % N = ((x * y) % N + (x * z) % N) % N;

 

 

以上是关于[LintCode] Fast Power的主要内容,如果未能解决你的问题,请参考以下文章

矩阵快速幂(Matrix_Fast_Power)

lintcode-easy-O Check Power of 2

[Lintcode]142. O Check Power of 2

[LintCode] O Check Power of 2

Fast Power

快速幂(Fast_Power)