Reputation: 1366
I want to code for calculating the value of pow(a,b)%MOD. I use C++ to code.
But the problem is the value of b can be very large. I know the log(b) time complexity method. But, the value of b might not fit in the data type "long long" of C++. For example b can be 1000000000 th Fibonacci number. Exact calculation of such a big number is itself, not possible (in time limits).
P.S. :
Upvotes: 10
Views: 11871
Reputation: 1
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
ll power(ll x, ll y)
{
if ( y == 0)
return 1;
ll temp = power(x, y / 2);
if (y % 2 == 0)
return (temp * temp) % mod;
else
return (((temp * temp) % mod) * x) % mod;
}
ll dmod(ll x)
{
return ((x + mod) % mod);
}
ll modular_power(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)ans = dmod(ans * x);
y /= 2;
x = dmod(x * x);
}
return ans;
}
int main()
{
ll a, b;
cin >> a >> b;
ll ans1 = modular_power(a, b);
ll ans2 = power(a, b);
// both answers are same
cout << ans1 << " " << ans2 ;
}
Upvotes: 0
Reputation:
But, the value of b might not fit in the data type "long long" of C++. For example b can be 1000000000 th Fibonacci number.
For things like this, there is a simple fix: recall
a^(b+c) == a^b * a^c mod d
You can compute the particular product you asked about with the same sort of recursion you use to compute Fibonacci numbers -- you don't need large numbers or modular exponentiation at all!
Another version that comes up sometimes is
a^(b*c) = (a^b)^c mod d
Upvotes: 0
Reputation: 103
I use this function to solve this problem
UVA 374 - Big Mod
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=310
// a^b % T
// with Exponentiation by squaring (http://en.wikipedia.org/wiki/Exponentiation_by_squaring#Basic_method)
// if a very large use
// R=(unsigned long long)(R*a)%T;
int restOfPot(long long a,int b,int T)
{
a%=T;
long long R=1;
while(b)
{
if(b&1) R=(R*a)%T;
a=(a*a)%T;
b>>=1;
}
return int(R);
}
Upvotes: 3
Reputation: 2405
For dealing with very large numbers, take a look at boost's Multiprecision library. It has a powm() function that works for this purpose well.
From Generic Integer Operations :
template <class Integer> Integer powm(const Integer& b, const Integer& p, const Integer& m);
Returns bp % m.
Example:
#include <boost/multiprecision/cpp_int.hpp>
boost::multiprecision::cpp_int pow("8912627233012800753578052027888001981");
boost::multiprecision::cpp_int mod("0x86f71688cdd2612c117d1f54bdae029");
boost::multiprecision::cpp_int base(12345);
boost::multiprecision::cpp_int result = powm(base, pow, mod);
std::cout << "result is: " << result << std::endl;
prints:
result is: 5758534182572671080415167723795472693
Upvotes: 1
Reputation: 14467
That's a typical task. Please (or, really, PLEASE!) read about the Euler's totient function.
And then the Euler's theorem.
The thing is you can dramatically reduce a^b to a^(b % phi(MOD)). Yes, you will need some kind of an integer factorization method, but still, no crazy ideas about actually calculating the power needed.
We did such samples by hand in my youth :) Even when the numbers where far beyond 32/64 bit range.
EDIT: Well, you live and learn. In 2008 the result is obtained:
"The totient is the discrete Fourier transform of the gcd: (Schramm (2008))"
So to calculate phi(b) one does not need to know its factors.
EDIT(2):
And the Carmichael's function is what you need to calculate to get the correct answer for any a, b and MOD.
Upvotes: 15
Reputation: 3497
I suggest using a specialized math library. Also this looks like crypto, so i suggest using a crypto library. GNU is bound to have one which you can use. This is because in crypto in many cases the exponent might be selected to give efficient calculation using shortcuts which normal math libraries cannot assume.
Upvotes: 0
Reputation: 36477
First: ^
in C/C++ is not the operator for powers. In fact, there is no operator for this. ^
represents a bitwise XOR. You'll have to use pow(base, exp)
which can be found in the header math.h
or cmath
.
For such huge numbers, using double
or long double
(exact lengths and and resulting datatypes might vary depending on your platform), but at some time you'll stumble upon precision issues, so depending on your use case, size of values your best bet might be using a custom datatype (edit: e.g. from one of the libraries found in one of the linked questions).
Upvotes: 0