📜  指数平方(快速模乘法)

📅  最后修改于: 2021-04-29 11:20:13             🧑  作者: Mango

给定两个数字baseexp ,我们需要在Modulo 10 ^ 9 + 7下计算base exp

例子:

Input : base = 2, exp = 2
Output : 4

Input  : base = 5, exp = 100000
Output : 754573817

在比赛中,为了计算一个大数的幂,我们得到一个模数值(一个大质数),因为x^y正在计算中,它可能会变得非常大,因此我们必须进行计算( x^y %模数值。)
我们可以通过在所有中间步骤中使用模数,然后以模数的方式,以幼稚的方式使用模数,
但在比赛中肯定会显示TLE。因此,我们能做些什么。
答案是我们可以通过平方来尝试求幂,这是一种计算数字幂的快速方法。
在这里,我们将讨论两种最常见/最重要的方法:

  1. 基本方法(二进制幂)
  2. 2^k -ary方法。

二进制求幂

如本文所述,我们将使用以下公式递归计算( x^y %模值):

{\displaystyle x^{n}={\begin{cases}x\,(x^{2})^{\frac {n-1}{2}},&{\mbox{if }}n{\mbox{ is odd}}\\(x^{2})^{\frac {n}{2}},&{\mbox{if }}n{\mbox{ is even}}.\end{cases}}}

C++
// C++ program to compute exponential 
// value under modulo using binary 
// exponentiation.
#include
using namespace std;
  
#define N 1000000007 // prime modulo value
  
long int exponentiation(long int base,
                        long int exp)
{
    if (exp == 0)
        return 1;
  
    if (exp == 1)
        return base % N;
  
    long int t = exponentiation(base, exp / 2);
    t = (t * t) % N;
  
    // if exponent is even value
    if (exp % 2 == 0)
        return t;
  
    // if exponent is odd value
    else
        return ((base % N) * t) % N;
}
  
// Driver Code
int main()
{
    long int base = 5;
    long int exp = 100000;
  
    long int modulo = exponentiation(base, exp);
    cout << modulo << endl;
    return 0;
}
  
// This Code is contributed by mits


Java
// Java program to compute exponential value under modulo
// using binary exponentiation.
import java.util.*;
import java.lang.*;
import java.io.*;
  
class exp_sq {
    static long N = 1000000007L; // prime modulo value
    public static void main(String[] args)
    {
        long base = 5;
        long exp = 100000;
  
        long modulo = exponentiation(base, exp);
        System.out.println(modulo);
    }
  
    static long exponentiation(long base, long exp)
    {
        if (exp == 0)
            return 1;
  
        if (exp == 1)
            return base % N;
  
        long t = exponentiation(base, exp / 2);
        t = (t * t) % N;
  
        // if exponent is even value
        if (exp % 2 == 0)
            return t;
  
        // if exponent is odd value
        else
            return ((base % N) * t) % N;
    }
}


Python3
# Python3 program to compute 
# exponential value under
# modulo using binary 
# exponentiation.
  
# prime modulo value
N = 1000000007;
      
# Function code 
def exponentiation(bas, exp):
    if (exp == 0):
        return 1;
    if (exp == 1):
        return bas % N;
      
    t = exponentiation(bas, int(exp / 2));
    t = (t * t) % N;
      
    # if exponent is
    # even value
    if (exp % 2 == 0):
        return t;
          
    # if exponent is
    # odd value
    else:
        return ((bas % N) * t) % N;
  
# Driver code
bas = 5;
exp = 100000;
  
modulo = exponentiation(bas, exp);
print(modulo);
  
# This code is contributed
# by mits


C#
// C# program to compute exponential
// value under modulo using binary 
// exponentiation.
using System;
  
class GFG {
      
    // prime modulo value
    static long N = 1000000007L;
      
    // Driver code
    public static void Main()
    {
        long bas = 5;
        long exp = 100000;
  
        long modulo = exponentiation(bas, exp);
        Console.Write(modulo);
    }
  
    static long exponentiation(long bas, long exp)
    {
        if (exp == 0)
            return 1;
  
        if (exp == 1)
            return bas % N;
  
        long t = exponentiation(bas, exp / 2);
        t = (t * t) % N;
  
        // if exponent is even value
        if (exp % 2 == 0)
            return t;
  
        // if exponent is odd value
        else
            return ((bas % N) * t) % N;
    }
}
  
// This code is contributed by nitin mittal.


PHP


C++
// C++ program to compute exponential value using (2^k)
// -ary method.
#include
using namespace std;
  
#define N 1000000007L; // prime modulo value
  
long exponentiation(long base, long exp)
{
    long t = 1L;
    while (exp > 0) 
    {
  
        // for cases where exponent
        // is not an even value
        if (exp % 2 != 0)
            t = (t * base) % N;
  
        base = (base * base) % N;
        exp /= 2;
    }
    return t % N;
}
  
// Driver code
int main()
{
    long base = 5;
    long exp = 100000;
  
    long modulo = exponentiation(base, exp);
    cout << (modulo);
    return 0;
}
  
// This code is contributed by Rajput-Ji


Java
// Java program to compute exponential value using (2^k)
// -ary method.
import java.util.*;
import java.lang.*;
import java.io.*;
  
class exp_sq {
    static long N = 1000000007L; // prime modulo value
    public static void main(String[] args)
    {
        long base = 5;
        long exp = 100000;
  
        long modulo = exponentiation(base, exp);
        System.out.println(modulo);
    }
  
    static long exponentiation(long base, long exp)
    {
        long t = 1L;
        while (exp > 0) {
  
            // for cases where exponent
            // is not an even value
            if (exp % 2 != 0)
                t = (t * base) % N;
  
            base = (base * base) % N;
            exp /= 2;
        }
        return t % N;
    }
}


Python3
# Python3 program to compute 
# exponential value 
# using (2^k) -ary method.
  
# prime modulo value
N = 1000000007; 
  
def exponentiation(bas, exp):
    t = 1;
    while(exp > 0): 
  
        # for cases where exponent
        # is not an even value
        if (exp % 2 != 0):
            t = (t * bas) % N;
  
        bas = (bas * bas) % N;
        exp = int(exp / 2);
    return t % N;
  
# Driver Code 
bas = 5;
exp = 100000;
  
modulo = exponentiation(bas,exp);
print(modulo);
  
# This code is contributed
# by mits


C#
// C# program to compute 
// exponential value 
// using (2^k) -ary method.
using System;
  
class GFG
{
// prime modulo value
static long N = 1000000007L; 
  
static long exponentiation(long bas, 
                           long exp)
{
    long t = 1L;
    while (exp > 0) 
    {
  
        // for cases where exponent
        // is not an even value
        if (exp % 2 != 0)
            t = (t * bas) % N;
  
        bas = (bas * bas) % N;
        exp /= 2;
    }
    return t % N;
}
  
// Driver Code    
public static void Main ()
{
    long bas = 5;
    long exp = 100000;
  
    long modulo = exponentiation(bas, 
                                 exp);
    Console.WriteLine(modulo);
}
}
  
//This code is contributed by ajit


PHP
 0) 
    {
  
        // for cases where exponent
        // is not an even value
        if ($exp % 2 != 0)
            $t = ($t * $bas) % $N;
  
        $bas = ($bas * $bas) % $N;
        $exp = (int)$exp / 2;
    }
    return $t % $N;
}
  
// Driver Code 
$bas = 5;
$exp = 100000;
  
$modulo = exponentiation($bas, 
                         $exp);
echo ($modulo);
  
// This code is contributed
// by ajit
?>


输出 :

754573817

2^k -ary方法:

在此算法中,我们将扩展基数的指数2^k (k> = 1),这与上述方法有点类似,除了我们不使用递归之外,此方法使用的内存和时间相对较少。

C++

// C++ program to compute exponential value using (2^k)
// -ary method.
#include
using namespace std;
  
#define N 1000000007L; // prime modulo value
  
long exponentiation(long base, long exp)
{
    long t = 1L;
    while (exp > 0) 
    {
  
        // for cases where exponent
        // is not an even value
        if (exp % 2 != 0)
            t = (t * base) % N;
  
        base = (base * base) % N;
        exp /= 2;
    }
    return t % N;
}
  
// Driver code
int main()
{
    long base = 5;
    long exp = 100000;
  
    long modulo = exponentiation(base, exp);
    cout << (modulo);
    return 0;
}
  
// This code is contributed by Rajput-Ji

Java

// Java program to compute exponential value using (2^k)
// -ary method.
import java.util.*;
import java.lang.*;
import java.io.*;
  
class exp_sq {
    static long N = 1000000007L; // prime modulo value
    public static void main(String[] args)
    {
        long base = 5;
        long exp = 100000;
  
        long modulo = exponentiation(base, exp);
        System.out.println(modulo);
    }
  
    static long exponentiation(long base, long exp)
    {
        long t = 1L;
        while (exp > 0) {
  
            // for cases where exponent
            // is not an even value
            if (exp % 2 != 0)
                t = (t * base) % N;
  
            base = (base * base) % N;
            exp /= 2;
        }
        return t % N;
    }
}

Python3

# Python3 program to compute 
# exponential value 
# using (2^k) -ary method.
  
# prime modulo value
N = 1000000007; 
  
def exponentiation(bas, exp):
    t = 1;
    while(exp > 0): 
  
        # for cases where exponent
        # is not an even value
        if (exp % 2 != 0):
            t = (t * bas) % N;
  
        bas = (bas * bas) % N;
        exp = int(exp / 2);
    return t % N;
  
# Driver Code 
bas = 5;
exp = 100000;
  
modulo = exponentiation(bas,exp);
print(modulo);
  
# This code is contributed
# by mits

C#

// C# program to compute 
// exponential value 
// using (2^k) -ary method.
using System;
  
class GFG
{
// prime modulo value
static long N = 1000000007L; 
  
static long exponentiation(long bas, 
                           long exp)
{
    long t = 1L;
    while (exp > 0) 
    {
  
        // for cases where exponent
        // is not an even value
        if (exp % 2 != 0)
            t = (t * bas) % N;
  
        bas = (bas * bas) % N;
        exp /= 2;
    }
    return t % N;
}
  
// Driver Code    
public static void Main ()
{
    long bas = 5;
    long exp = 100000;
  
    long modulo = exponentiation(bas, 
                                 exp);
    Console.WriteLine(modulo);
}
}
  
//This code is contributed by ajit

的PHP

 0) 
    {
  
        // for cases where exponent
        // is not an even value
        if ($exp % 2 != 0)
            $t = ($t * $bas) % $N;
  
        $bas = ($bas * $bas) % $N;
        $exp = (int)$exp / 2;
    }
    return $t % $N;
}
  
// Driver Code 
$bas = 5;
$exp = 100000;
  
$modulo = exponentiation($bas, 
                         $exp);
echo ($modulo);
  
// This code is contributed
// by ajit
?>

输出 :

754573817

应用范围:
除了快速计算x^y这种方法还有其他一些优点,例如在密码学中使用它来计算矩阵幂等。