This question already has answers here:
How to calculate modulus of large numbers?
(10 answers)
Closed 9 years ago.
I have two numbers A and B
where A and B can be in the range 1<= A,B <=100^100000
How can we find the value of A^B modulo some M in C++ ??
In the duplicate I pointed out, the solution I particularly like is https://stackoverflow.com/a/8972838/1967396 (see there for attribution and references)
For your convenience I reproduce the code here (wrapped into an SCCE - but using C, not C++):
#include <stdio.h>
int modular(int base, unsigned int exp, unsigned int mod)
{
int x = 1;
int i;
int power = base % mod;
for (i = 0; i < sizeof(int) * 8; i++) {
int least_sig_bit = 0x00000001 & (exp >> i);
if (least_sig_bit)
x = (x * power) % mod;
power = (power * power) % mod;
}
return x;
}
int main(void) {
printf("123^456mod567 = %d\n", modular(123, 456, 567));
}
Amazing, isn't it.
use the formula (a*b)mod m = (a*(b (mod m))) (mod m). For more details see the wiki page Modular exponentiation
Another solution assumes that your M is fixed (or at least that you need to compute A^B many times with the same M).
Step 1: compute the Euler's totient function (this requires a factorization of M, so it's quite expensive). Let's call this number k.
Due to the Fermat's little theorem, your answer is simply:
(a % M)^(b % k)
Now, unless M is a large prime number, this greatly simplify the problem.
The above problem can be solved using the code snippet below.
Thus to ensure this code does not overflow, check that n * n <= 2 ^ 31.
int modPow(int base, int exp, int n) {
base = base%n;
if (exp == 0)
return 1;
else if (exp == 1)
return base;
else if (exp%2 == 0)
return modPow(base*base%n, exp/2, n);
else
return base*modPow(base, exp-1, n)%n;
}
Related
This question already has answers here:
Why does pow(n,2) return 24 when n=5, with my compiler and OS?
(4 answers)
Closed 2 years ago.
For the below code:
int digsum(ll num) { //function to calculate sum of digits
if (num < 0)
num = abs(num);
int ans = 0;
while (num != 0) {
ans = ans + num % 10;
num = num / 10;
}
return ans;
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
int a, b, c, cnt = 0;
long long x;
cin >> a >> b >> c;
for (int i = 0; i <= 72; i++) {
x = (b * (pow(i, a))) + c;
if (i == digsum(x) && x < mod) {
cout << x << " ";
}
}
return 0;
}
In the case a,b,c = 3,2,8 respectively and i=19;
pow(19,3) is supposed to calculate 19^3 but when I replace pow by (19x19x19), this specific case is getting satisfied, where as that wasn't the case with the pow function.
Can someone explain what the problem is?
My psychic powers suggest that your standard library's implementation of pow is not precise. I recall a discussion on SO a while back on this topic. Remember, pow returns a floating point value. I can't repro it, but it's entirely possibly your invocation of pow(19,3) returns 6858.999999999 or similar due to the way it's optimized.
Indeed, this this page says as much:
Due to rounding errors in floating point numbers, the results of pow() may not be precise (even if you pass it integers or whole numbers).
Also, this question and answer suggests the same thing.
I wouldn't have suspected it, but there you go.
Consider doing this as a workaround:
long long power = nearbyint(pow(i,a));
x = b * power + c;
I am doing this coding question where they ask you to enter numbers N and M, and you are supposed to output the Nth fibonacci number mod M. My code runs rather slowly and I would like to learn how to speed it up.
#include<bits/stdc++.h>
using namespace std;
long long fib(long long N)
{
if (N <= 1)
return N;
return fib(N-1) + fib(N-2);
}
int main ()
{
long long N;
cin >> N;
long long M;
cin >> M;
long long b;
b = fib(N) % M;
cout << b;
getchar();
return 0;
}
While the program you wrote is pretty much the go-to example of recursion in education, it is really a pretty damn bad algorithm as you have found out. Try to write up the call tree for fib(7) and you will find that the number of calls you make balloons dramatically.
There are many ways of speeding it up and keeping it from recalculating the same values over and over. Somebody already linked to a bunch of algorithms in the comments - a simple loop can easily make it linear in N instead of exponential.
One problem with this though is that fibonacci numbers grow pretty fast: You can hold fib(93) in a 64 bit integer, but fib(94) overflows it.
However, you don't want the N'th fibonacci number - you want the N'th mod M. This changes the challenge a bit, because as long as M is smaller than MAX_INT_64 / 2 then you can calculate fib(N) mod M for any N.
Turn your attention to Modular arithmetic and the congruence relations. Specifically the one for addition, which says (changed to C++ syntax and simplified a bit):
If a1 % m == b1 and a2 % m == b2 then (a1 + a2) % m == (b1 + b2) % m
Or, to give an example: 17 % 3 == 2, 22 % 3 == 1 => (17 + 22) % 3 == (2 + 1) % 3 == 3 % 3 == 0
This means that you can put the modulo operator into the middle of your algorithm so that you never add big numbers together and never overflow. This way you can easily calculate f.ex. fib(10000) mod 237.
There is one simple optimatimization in calling fib without calculating duplicate values. Also using loops instead of recursion may speed up the process:
int fib(int N) {
int f0 = 0;
int f1 = 1;
for (int i = 0; i < N; i++) {
int tmp = f0 + f1;
f0 = f1;
f1 = tmp;
}
return f1;
}
You can apply the modulo operator sugested by #Frodyne on top of this.
1st observation is that you can turn the recursion into a simple loop:
#include <cstdint>
std::uint64_t fib(std::uint16_t n) {
if (!n)
return 0;
std::uint64_t result[]{ 0,1 };
bool select = 1;
for (auto i = 1; i < n; ++i , select=!select)
{
result[!select] += result[select];
};
return result[select];
};
next you can memoize it:
#include <cstdint>
#include <vector>
std::uint64_t fib(std::uint16_t n) {
static std::vector<std::uint64_t> result{0,1};
if (result.size()>n)
return result[n];
std::uint64_t back[]{ result.crbegin()[1],result.back() };
bool select = 1;
result.reserve(n + 1);
for (auto i=result.size(); i < result.capacity();++i, select = !select)
result.push_back(back[!select] += back[select]);
return result[n];
};
Another option would be an algebraic formula.
cheers,
FM.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
For example, A=10^17, B=10^17 (<64bits)
Typically, in the algorithm above, the calculs to compute F(2n) and those to compute F(2n+1) exceeds long long int types and we can't use modular computation in it.
The best algorithm to compute it I talk is fibonacci fast doubling:
F(0) = 0, F(1) = 1.
F(2n) = F(n)(2*F(n+1) – F(n)).
F(2n + 1) = F(n)2 + F(n+1)2.
Do you know some types in new C++14 (g++8.3.0 or llvm-clang C++) to use to avoid overflow.
I tried __float128 that is best than long double with no success. (see the g++ code above)
I have heard of the existence of __int128 and __int256 with no printf possibilities but I haven't try it.
Are they availailable in g++ 8.3.0 or are there other fast means to handle 128bits ints to do intermediate calculs you can think of?
(time perfs are important)
#include <bits/stdc++.h>
using namespace std;
__float128 a,b,c,d;
long long mod;
void fast_fib(long long n,long long ans[]){
if(n == 0){
ans[0] = 0;
ans[1] = 1;
return;
}
fast_fib((n/2),ans);
a = ans[0]; /* F(n) */
b = ans[1]; /* F(n+1) */
c = 2*b - a;
if(c < 0) c += mod;
c = (a * c); /* F(2n) */
while(c>=mod)c-=mod;
d = (a*a + b*b); /* F(2n + 1) */
while(d>=mod)d-=mod;
if(n%2 == 0){
ans[0] = c;
ans[1] = d;
}
else{
ans[0] = d;
ans[1] = c+d;
}
}
int main(){
int T=1000;
long long n;
while(T--){
scanf("%lld %lld",&n,&mod);
long long ans[2]={0};
fast_fib(n,ans);
printf("%lld\n", ans[0]);
}
return 0;
}
with __float128 I can't implement the modulo efficiently and a,b,c,d must store 128 bits data.
You don't need any floating point type for the calculations. You can use long long type only. First, you need a function that multiplicates two long long numbers (that are less than 10^18) modulo B. This can be done with the similar to exponentiation by squaring method:
long long multiply(long long a, long long b, long long M) {
long long res = 0;
long long d = a;
while (b > 0) {
if (b & 1) {
res = (res + d) % M;
}
b /= 2;
d = (d + d) % M;
}
return res;
}
Second, you need to add modulo operation to almost all of your arithmetic operations. And you definitely need to replace these loops while(c>=mod)c-=mod (they could be very slow) with the addition of % mod to the corresponding operations.
Your code with __float_128 replaced with long long and with proper modular arithmetic: https://ideone.com/t6R7Tf
Another thing you can do is to use (as was mentioned in the comments) Boost.Multiprecision or non-standard __int128 type (if supported) instead of long long type with complicated multiplication.
Also, you could use a slightly different (but using the same math actually) approach that seems more obvious to me - the Fibonacci numbers matrix formula
To calculate the Nth power of matrix you can use exponentiation by squaring doing all operations modulo B.
This problem's answer turns out to be calculating large binomial coefficients modulo prime number using Lucas' theorem. Here's the solution to that problem using this technique: here.
Now my questions are:
Seems like my code expires if the data increases due to overflow of variables. Any ways to handle this?
Are there any ways to do this without using this theorem?
EDIT: note that as this is an OI or ACM problem, external libs other than original ones are not permitted.
Code below:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#define N 100010
long long mod_pow(int a,int n,int p)
{
long long ret=1;
long long A=a;
while(n)
{
if (n & 1)
ret=(ret*A)%p;
A=(A*A)%p;
n>>=1;
}
return ret;
}
long long factorial[N];
void init(long long p)
{
factorial[0] = 1;
for(int i = 1;i <= p;i++)
factorial[i] = factorial[i-1]*i%p;
//for(int i = 0;i < p;i++)
//ni[i] = mod_pow(factorial[i],p-2,p);
}
long long Lucas(long long a,long long k,long long p)
{
long long re = 1;
while(a && k)
{
long long aa = a%p;long long bb = k%p;
if(aa < bb) return 0;
re = re*factorial[aa]*mod_pow(factorial[bb]*factorial[aa-bb]%p,p-2,p)%p;
a /= p;
k /= p;
}
return re;
}
int main()
{
int t;
cin >> t;
while(t--)
{
long long n,m,p;
cin >> n >> m >> p;
init(p);
cout << Lucas(n+m,m,p) << "\n";
}
return 0;
}
This solution assumes that p2 fits into an unsigned long long. Since an unsigned long long has at least 64 bits as per standard, this works at least for p up to 4 billion, much more than the question specifies.
typedef unsigned long long num;
/* x such that a*x = 1 mod p */
num modinv(num a, num p)
{
/* implement this one on your own */
/* you can use the extended Euclidean algorithm */
}
/* n chose m mod p */
/* computed with the theorem of Lucas */
num modbinom(num n, num m, num p)
{
num i, result, divisor, n_, m_;
if (m == 0)
return 1;
/* check for the likely case that the result is zero */
if (n < m)
return 0;
for (n_ = n, m_ = m; m_ > 0; n_ /= p, m_ /= p)
if (n_ % p < m_ % p)
return 0;
for (result = 1; n >= p || m >= p; n /= p, m /= p) {
result *= modbinom(n % p, m % p, p);
result %= p;
}
/* avoid unnecessary computations */
if (m > n - m)
m = n - m;
divisor = 1;
for (i = 0; i < m; i++) {
result *= n - i;
result %= p;
divisor *= i + 1;
divisor %= p;
}
result *= modinv(divisor, p);
result %= p;
return result;
}
An infinite precision integer seems like the way to go.
If you are in C++,
the PicklingTools library has an "infinite precision" integer (similar to
Python's LONG type). Someone else suggested Python, that's a reasonable
answer if you know Python. if you want to do it in C++, you can
use the int_n type:
#include "ocval.h"
int_n n="012345678910227836478627843";
n = n + 1; // Can combine with other plain ints as well
Take a look at the documentation at:
http://www.picklingtools.com/html/usersguide.html#c-int-n-and-the-python-arbitrary-size-ints-long
and
http://www.picklingtools.com/html/faq.html#c-and-otab-tup-int-un-int-n-new-in-picklingtools-1-2-0
The download for the C++ PicklingTools is here.
You want a bignum (a.k.a. arbitrary precision arithmetic) library.
First, don't write your own bignum (or bigint) library, because efficient algorithms (more efficient than the naive ones you learned at school) are difficult to design and implement.
Then, I would recommend GMPlib. It is free software, well documented, often used, quite efficient, and well designed (with perhaps some imperfections, in particular the inability to plugin your own memory allocator in replacement of the system malloc; but you probably don't care, unless you want to catch the rare out-of-memory condition ...). It has an easy C++ interface. It is packaged in most Linux distributions.
If it is a homework assignment, perhaps your teacher is expecting you to think more on the math, and find, with some proof, a way of solving the problem without any bignums.
Lets suppose that we need to compute a value of (a / b) mod p where p is a prime number. Since p is prime then every number b has an inverse mod p. So (a / b) mod p = (a mod p) * (b mod p)^-1. We can use euclidean algorithm to compute the inverse.
To get (n over k) we need to compute n! mod p, (k!)^-1, ((n - k)!)^-1. Total time complexity is O(n).
UPDATE: Here is the code in c++. I didn't test it extensively though.
int64_t fastPow(int64_t a, int64_t exp, int64_t mod)
{
int64_t res = 1;
while (exp)
{
if (exp % 2 == 1)
{
res *= a;
res %= mod;
}
a *= a;
a %= mod;
exp >>= 1;
}
return res;
}
// This inverse works only for primes p, it uses Fermat's little theorem
int64_t inverse(int64_t a, int64_t p)
{
assert(p >= 2);
return fastPow(a, p - 2, p);
}
int64_t binomial(int64_t n, int64_t k, int64_t p)
{
std::vector<int64_t> fact(n + 1);
fact[0] = 1;
for (auto i = 1; i <= n; ++i)
fact[i] = (fact[i - 1] * i) % p;
return ((((fact[n] * inverse(fact[k], p)) % p) * inverse(fact[n - k], p)) % p);
}
I have found a formula that solves a problem but I can't make it work for large numbers. The n-th factor would be the (n-1)-th factor + (n-1)*(n-1) + n * n
So I wrote this function:
inline long long int formula(long long int n)
{
if(n==1)return 1;
return formula(n-1)+(n-1)*(n-1)+*n*n;
}
and since the answer has to be calculated modulo 666013, I added this (MOD=666013):
inline long long int formula(long long int n)
{
if(n==1)return 1;
return ((formula(n-1)%MOD+(1LL*(n-1)*(n-1))%MOD)%MOD+(1LL*n*n)%MOD)%MOD;
}
I probably didn't use modulo correctly. My function has to work for numbers as large as 2.000.000.000 and it stops working at about 30.000
EDIT: I've tried using a loop and I still can't make it work for numbers larger than 20.000.000. This is what I'm using:
ans=1;
for(i=2;i<=n;i++)
{
ans=(ans%MOD+1LL*(i-1)*(i-1)%MOD+1LL*i*i%MOD)%MOD;
}
I don't understand why you are using a recursive function for this. It will work at a low number of calls, but if you recursively call it a few milion times, well... it will not. The reason is that you are calling a function within another function within another function... too many times provoking the program to collapse or named as "Stack Overflow".
The best possible way to overcome this, is to use a loop to fix it up! Just iterate from 0 to n (n being the number you want to obtain).
Simplify as much as possible in order to be able to see the requirements:
typedef long long val_t;
#define MOD ((val_t) 666013)
// for really big numbers, change #if to 1
#if 0
#define MODOF(_x) ((_x) % MOD)
#else
#define MODOF(_x) (_x)
#endif
#define SQR(_i) MODOF((_i) * (_i))
val_t
formula(val_t n)
{
val_t i;
val_t ans;
ans = 0;
for (i = 1; i <= n; ++i) {
ans += SQR(i-1);
ans += SQR(i);
ans %= MOD;
}
return ans;
}
UPDATE: I'm so used to seeing factorial herein that I wrote the wrong formula. Now corrected.
Iterative version of your code is in below . You can use it
inline long long int formula(long long int n)
{
long long f = 1;
for (int i = 2; i <= n; i++)
{
f = ((f % MOD + (1LL * (i - 1)*(i - 1)) % MOD) % MOD + (1LL * i*i) % MOD) % MOD;
}
return f;
}
The loop will take quite a long time if you need to calculate it for size of 2 billion. However, the recursive equation leads trivially to
sum [i * i+(i-1)*(i-1)] = sum [2* i * i - 2*i + 1].
You can use the equation for the sum of first n squares and the arithmetic sequence to simplify this to:
2*n(n * n + 1) / 3
Now you can further reduce this using a * b % c = (a % c) * (b %c). However, the division by 3 and modulus operation does not commute. So you need to write the equation as
( ((2*(n % MOD)) %MOD) * (((n % MOD) * (n % MOD)) +1) %MOD) * 444009) % MOD,
where the 444009 is the modular inverse of 3 mod MOD, i.e, 3*444009 % MOD =1.
EDIT: Added the discussion about commuting modulus and division operators as pointed out by Raymond Chen the modulus and division do not commute.