zoukankan      html  css  js  c++  java
  • [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;

  • 相关阅读:
    DL/T 467-2019 电站磨煤机及制粉系统性能试验
    fidlder-05(拦截并修改数据)
    fiddler-04(怎么对APP抓包)
    Redis5设计与源码分析读后感(二)简单动态字符串SDS
    Jedis连接搭建在阿里云服务器上的Redis,基于Linux(CentOS7)
    centos7下安装redis6.0版本+3种启动方式
    Linux下端口被占用的解决方法
    Linux卸载Nginx
    linux中普通用户修改密码出现(passwd:Authentication token manipulation error)
    linux重置密码提示与用户名相似该怎么解决?
  • 原文地址:https://www.cnblogs.com/lz87/p/7524329.html
Copyright © 2011-2022 走看看