Find (a^b)%m where ‘a’ ‘b’ and ‘c’ is very large number
Last Updated :
08 Mar, 2024
Given three numbers a, b, and m where10^9 ≤ a, b ≤ 10^9. Given very large ‘m’ containing 10^18+7 and m is a prime number, the task is to find (a ^ b) % m.
Example:
Input: a = “5541548454152524154”, b = “946646454116451”, M = 1e18+7
Output: 588288874981883904
Input: a = “5454656454154”, b = “5646546546465446”, M = 1e18+7
Output: 654515516062826496
Approach: To solve the problem follow the below observations:
In this type of case, we can face a problem with using Binary Exponentiation. As M is 1018+7 then in some cases we can not store a value greater than INT_MAX.
According to Fermat’s little theorem and Modular Exponentiation:
- a ^ (p – 1) mod p = 1, When p is prime.
From this, as of the problem, M is prime, express A ^ B mod M as follows:
A^B mod M = ( A^(M-1) * A^(M-1) *…….* A^(M-1) * A^(x) ) mod M
- Where x is B mod M – 1 and A ^ (M – 1) continues B/(M-1) times
Now, from Fermat’s Little Theorem, A ^ (M-1) mod M = 1.Hence,
A^B mod M = ( 1 * 1 * ……. * 1 * A^(x) ) mod M
- Hence mod B with M-1 to reduce the number to a smaller one and then use the power() method to compute (a ^ b)%m.
We can write binary exponential code considering a ≤ 1018 and b ≤ 1018. if a > 1018 or b > 1018 we can go through the method mentioned in 2 and 3 no article and then apply this for Big m.
Below is the implementation for the above approach:
C++
#include <iostream>
using namespace std;
const long long M = 1e9 + 7;
long long BinExp( long long a, long long b)
{
long long ans = 1;
while (b > 0) {
if (b & 1) {
ans = (ans * a) % M;
}
a = (a * a) % M;
b >>= 1;
}
return ans;
}
int main()
{
cout << BinExp(2, 10);
return 0;
}
|
Java
class GFG {
static final long M = 1000000007 ;
public static long BinExp( long a, long b)
{
long ans = 1 ;
while (b > 0 ) {
if ((b & 1 ) == 1 ) {
ans = (ans * a) % M;
}
a = (a * a) % M;
b >>= 1 ;
}
return ans;
}
public static void main(String[] args)
{
System.out.println(BinExp( 2 , 10 ));
}
}
|
C#
using System;
public class Program
{
const long M = 1000000007;
public static long BinExp( long a, long b)
{
long ans = 1;
while (b > 0)
{
if ((b & 1) == 1)
{
ans = (ans * a) % M;
}
a = (a * a) % M;
b >>= 1;
}
return ans;
}
public static void Main()
{
Console.WriteLine(BinExp(2, 10));
}
}
|
Javascript
function GFG(a, b) {
const M = 1e9 + 7;
let ans = 1;
while (b > 0) {
if (b & 1) {
ans = (ans * a) % M;
}
a = (a * a) % M;
b >>= 1;
}
return ans;
}
function main() {
const result = GFG(2, 10);
console.log(result);
}
main();
|
Python3
M = 10 * * 9 + 7
def BinExp(a, b):
ans = 1
while b > 0 :
if b & 1 :
ans = (ans * a) % M
a = (a * a) % M
b >> = 1
return ans
print (BinExp( 2 , 10 ))
|
It will run fine when M will be ordered 107. But when M is the order of 1018 then we will face a problem. So, there are 2 following cases:
- When (ans * a ) is occurring then if a is in order of 10^18 and ans is also in the same order then an overflow can take place which causes a negative answer.
- When (a * a ) is occurring then if a is in order of 10^18 then an overflow can take place as 10^18 * 10^18 = 10^36 which causes a negative answer.
To tackle this we can follow the binary multiplication rule:
In this case we can use (a + a + a + a…) in the position of a * a . In words we can say that instead of doing direct multiplication we can use multiplication by cosecutive addition and taking modulous . And in this case We can get At most 2 * 10^18 which is in range.
Binary Multiplication Process:
a + a ≤ 2 * 10^18
(a + a) % M ≤ 10^18
(a +a + a) ≤ 2 * 10^18
(a + a + a) % M ≤ 10^18 … So on.
We can do the process following Binary exponentiation. In Binary multiplication when the bit of the number is set then we will add (ans + a) in place of (ans * a) and we will add (a + a) in place of (a * a) so that no overflow occurred.
C++
#include <iostream>
using namespace std;
const int M = 1000000007;
int BinMul( int a, int b) {
int ans = 1;
while (b > 0) {
if (b & 1) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1;
}
return ans;
}
int main() {
int a = 10;
int b = 20;
int result = BinMul(a, b);
cout << "Result: " << result << endl;
return 0;
}
|
Java
public class Main {
static final int M = 1000000007 ;
static int binMul( int a, int b) {
int ans = 1 ;
while (b > 0 ) {
if ((b & 1 ) == 1 ) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1 ;
}
return ans;
}
public static void main(String[] args) {
int a = 10 ;
int b = 20 ;
int result = binMul(a, b);
System.out.println( "Result: " + result);
}
}
|
Python
def bin_mul(a, b):
ans = 1
M = 1000000007
while b > 0 :
if b & 1 :
ans = (ans + a) % M
a = (a + a) % M
b >> = 1
return ans
if __name__ = = "__main__" :
a = 10
b = 20
result = bin_mul(a, b)
print ( "Result:" , result)
|
C#
using System;
class MainClass {
const long M = 1000000007;
static long BinMul( long a, long b)
{
long ans = 1;
while (b > 0) {
if ((b & 1) == 1) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1;
}
return ans;
}
public static void Main( string [] args)
{
long a = 10;
long b = 20;
long result = BinMul(a, b);
Console.WriteLine( "Result: " + result);
}
}
|
Javascript
const M = 1000000007;
function BinMul(a, b) {
let ans = 1;
while (b > 0) {
if (b & 1) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1;
}
return ans;
}
let a = 10;
let b = 20;
let result = BinMul(a, b);
console.log( "Result: " + result);
|
This function will help us to find (A * B) when A and B are ordered of 10^18. So in Binary Exponentiation in place of multiplication, we will use this function to avoid overflow. Combining all the above approaches we can get a proper approach.
Below is the implementation of the Above Approach:
C++
#include <iostream>
using namespace std;
const long long M = 1e18 + 7;
long long MODA(string num)
{
long long res = 0;
for ( long long int i = 0; i < num.length(); i++)
res = (res * 10 + num[i] - '0' ) % M;
return res;
}
long long MODB(string b)
{
long long res = 0;
for ( int i = 0; i < b.length(); i++)
res = (res * 10 + b[i] - '0' ) % (M - 1);
return res;
}
long long BinMul( long long a, long long b)
{
long long ans = 0;
while (b > 0) {
if (b & 1) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1;
}
return ans;
}
long long BinExp( long long a, long long b)
{
long long ans = 1;
while (b > 0) {
if (b & 1) {
ans = BinMul(a, ans);
}
a = BinMul(a, a);
b >>= 1;
}
return ans;
}
int main()
{
string a = "5541548454152524154" , b = "946646454116451" ;
long long aa = MODA(a);
long long bb = MODB(b);
cout << BinExp(aa, bb);
return 0;
}
|
Java
import java.math.BigInteger;
public class Main {
static final long M = 1000000000000000007L;
static long MODA(String num) {
long res = 0 ;
for ( int i = 0 ; i < num.length(); i++) {
res = (res * 10 + num.charAt(i) - '0' ) % M;
}
return res;
}
static long MODB(String b) {
long res = 0 ;
for ( int i = 0 ; i < b.length(); i++) {
res = (res * 10 + b.charAt(i) - '0' ) % (M - 1 );
}
return res;
}
static long BinMul( long a, long b) {
long ans = 0 ;
while (b > 0 ) {
if ((b & 1 ) == 1 ) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1 ;
}
return ans;
}
static long BinExp( long a, long b) {
long ans = 1 ;
while (b > 0 ) {
if ((b & 1 ) == 1 ) {
ans = BinMul(a, ans);
}
a = BinMul(a, a);
b >>= 1 ;
}
return ans;
}
public static void main(String[] args) {
String a = "5541548454152524154" ;
String b = "946646454116451" ;
long aa = MODA(a);
long bb = MODB(b);
System.out.println(BinExp(aa, bb));
}
}
|
C#
using System;
class Program
{
const long M = 1000000000000000007;
static long MODA( string num)
{
long res = 0;
foreach ( char digit in num)
{
res = (res * 10 + (digit - '0' )) % M;
}
return res;
}
static long MODB( string b)
{
long res = 0;
foreach ( char digit in b)
{
res = (res * 10 + (digit - '0' )) % (M - 1);
}
return res;
}
static long BinMul( long a, long b)
{
long ans = 0;
while (b > 0)
{
if ((b & 1) != 0)
{
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1;
}
return ans;
}
static long BinExp( long a, long b)
{
long ans = 1;
while (b > 0)
{
if ((b & 1) != 0)
{
ans = BinMul(a, ans);
}
a = BinMul(a, a);
b >>= 1;
}
return ans;
}
static void Main()
{
string a = "5541548454152524154" ;
string b = "946646454116451" ;
long aa = MODA(a);
long bb = MODB(b);
Console.WriteLine(BinExp(aa, bb));
}
}
|
Javascript
const M = BigInt(10 ** 18 + 7);
function MODA(num) {
let res = BigInt(0);
for (let i = 0; i < num.length; i++) {
res = (res * BigInt(10) + BigInt(num[i]) - BigInt( '0' )) % M;
}
return res;
}
function MODB(b) {
let res = BigInt(0);
for (let i = 0; i < b.length; i++) {
res = (res * BigInt(10) + BigInt(b[i]) - BigInt( '0' )) % (M - BigInt(1));
}
return res;
}
function BinMul(a, b) {
let ans = BigInt(0);
while (b > 0n) {
if (b & 1n) {
ans = (ans + a) % M;
}
a = (a + a) % M;
b >>= 1n;
}
return ans;
}
function BinExp(a, b) {
let ans = BigInt(1);
while (b > 0n) {
if (b & 1n) {
ans = BinMul(a, ans);
}
a = BinMul(a, a);
b >>= 1n;
}
return ans;
}
const a = "5541548454152524154" ;
const b = "946646454116451" ;
const aa = MODA(a);
const bb = MODB(b);
console.log(BinExp(aa, bb).toString());
|
Python3
def moda(num):
res = 0
for i in range ( len (num)):
res = (res * 10 + int (num[i])) % M
return res
def modb(b):
res = 0
for i in range ( len (b)):
res = (res * 10 + int (b[i])) % (M - 1 )
return res
def binmul(a, b):
ans = 0
while b > 0 :
if b & 1 :
ans = (ans + a) % M
a = (a + a) % M
b >> = 1
return ans
def binexp(a, b):
ans = 1
while b > 0 :
if b & 1 :
ans = binmul(a, ans)
a = binmul(a, a)
b >> = 1
return ans
if __name__ = = "__main__" :
M = 10 * * 18 + 7
a = "5541548454152524154"
b = "946646454116451"
aa = moda(a)
bb = modb(b)
print (binexp(aa, bb))
|
Output
588288874981883904
Time Complexity: O((log(N))2)
Auxiliary Space: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...