What is the fastest way to compute large power of 2 modulo a number

前端 未结 5 2151
南方客
南方客 2020-12-06 02:48

For 1 <= N <= 1000000000, I need to compute 2N mod 1000000007, and it must be really fast!
My current approach i

相关标签:
5条回答
  • 2020-12-06 03:30

    This method doesn't use recursion with O(log(n)) complexity. Check this out.

    #define ull unsigned long long
    #define MODULO 1000000007
    
    ull PowMod(ull n)
    {
        ull ret = 1;
        ull a = 2;
        while (n > 0) {
            if (n & 1) ret = ret * a % MODULO;
            a = a * a % MODULO;
            n >>= 1;
        }
        return ret;
    }
    

    And this is pseudo from Wikipedia (see Right-to-left binary method section)

    function modular_pow(base, exponent, modulus)
    Assert :: (modulus - 1) * (base mod modulus) does not overflow base
    result := 1
    base := base mod modulus
    while exponent > 0
        if (exponent mod 2 == 1):
           result := (result * base) mod modulus
        exponent := exponent >> 1
        base := (base * base) mod modulus
    return result
    
    0 讨论(0)
  • 2020-12-06 03:33

    It can be solved in O((log n)^2). Try this approach:-

    unsigned long long int fastspcexp(unsigned long long int n)
    {
        if(n==0)
            return 1;
        if(n%2==0)
            return (((fastspcexp(n/2))*(fastspcexp(n/2)))%1000000007);
        else
            return ( ( ((fastspcexp(n/2)) * (fastspcexp(n/2)) * 2) %1000000007 ) ); 
    }
    

    This is a recursive approach and is pretty fast enough to meet the time requirements in most of the programming competitions.

    0 讨论(0)
  • 2020-12-06 03:38

    You can solve it in O(log n).

    For example, for n = 1234 = 10011010010 (in base 2) we have n = 2 + 16 + 64 + 128 + 1024, and thus 2^n = 2^2 * 2^16 * 2^64 * 2^128 * 2 ^ 1024.

    Note that 2^1024 = (2^512)^2, so that, given you know 2^512, you can compute 2^1024 in a couple of operations.

    The solution would be something like this (pseudocode):

    const ulong MODULO = 1000000007;
    
    ulong mul(ulong a, ulong b) {
        return (a * b) % MODULO;
    }
    
    ulong add(ulong a, ulong b) {
        return (a + b) % MODULO;
    }
    
    int[] decompose(ulong number) {
        //for 1234 it should return [1, 4, 6, 7, 10]
    }
    
    //for x it returns 2^(2^x) mod MODULO
    // (e.g. for x = 10 it returns 2^1024 mod MODULO)
    ulong power_of_power_of_2_mod(int power) {
        ulong result = 1;
        for (int i = 0; i < power; i++) {
            result = mul(result, result);
        }
        return result;
    }
    
    //for x it returns 2^x mod MODULO
    ulong power_of_2_mod(int power) {
        ulong result = 1;
        foreach (int metapower in decompose(power)) {
            result = mul(result, power_of_power_of_2_mod(metapower));
        }
        return result;
    }
    

    Note that O(log n) is, in practice, O(1) for ulong arguments (as log n < 63); and that this code is compatible with any uint MODULO (MODULO < 2^32), independent of whether MODULO is prime or not.

    0 讨论(0)
  • 2020-12-06 03:39

    This will be faster (code in C):

    typedef unsigned long long uint64;
    
    uint64 PowMod(uint64 x, uint64 e, uint64 mod)
    {
      uint64 res;
    
      if (e == 0)
      {
        res = 1;
      }
      else if (e == 1)
      {
        res = x;
      }
      else
      {
        res = PowMod(x, e / 2, mod);
        res = res * res % mod;
        if (e % 2)
          res = res * x % mod;
      }
    
      return res;
    }
    
    0 讨论(0)
  • 2020-12-06 03:48

    If u also want to store that array ie. (2^i)%mod [i=0 to whatever] than:

    long mod = 1000000007;
    long int pow_mod[ele]; //here 'ele' = maximum power upto which you want to store 2^i
    pow_mod[0]=1; //2^0 = 1
    for(int i=1;i<ele;++i){
        pow_mod[i] = (pow_mod[i-1]*2)%mod;
    }
    

    I hope it'll be helpful to someone.

    0 讨论(0)
提交回复
热议问题