C++: fast modular exponentation - c++

I'm a computer science student and i have a problem where i must use the fast modular exponentation.
With this code that i made, the corrector says me that the output in some cases is incorrect, but it shouldn't be.
unsigned long long int pow(int a, int n, int M)
{
if(n==0)
return 1;
if(n==1)
return a;
unsigned long long tmp=pow(a, n/2, M)%M;
if(n%2==0)
return ((tmp)*(tmp))%M;
return ((tmp*tmp)*(a%M))%M;
}
Instead with this other code i pass all the test cases.
unsigned long long int pow(int a, int n, int M)
{
if(n==0)
return 1;
if(n==1)
return a;
unsigned long long tmp;
if(n%2==0){
tmp=pow(a, n/2, M)%M;
return (tmp*tmp)%M;
}
tmp=pow(a, n-1, M)%M;
return (tmp*(a%M))%M;
}
So my question is why with the first code i don't pass all the test cases?

First, if n == 1, the return value should be a % M, not a. Second, the product (tmp * tmp) * (a % M) can overflow, and should be computed as ((tmp * tmp) % M) * (a % M).
The condition n == 1 doesn't need any special treatment, and the code can be simplified to:
unsigned long long int pow(unsigned int a, unsigned int n, unsigned int m) {
if (n == 0)
return 1;
auto tmp = pow(a, n / 2, m) % m;
tmp *= tmp;
if (n % 2)
tmp = (tmp % m) * (a % m);
return tmp % m;
}

Related

Division using right shift operator gives TLE while normal division works fine

I'm trying to submit this leetcode problem Pow(x,n) using iterative approach.
double poww(double x, int n)
{
if (n == 0)
return 1;
double ans = 1;
double temp = x;
while (n)
{
if (n & 1)
{
ans *= temp;
}
temp *= temp;
n = (n >> 1);
}
return ans;
}
double myPow(double x, int n)
{
if (n == 0)
return 1.0;
if (n < 0)
return 1 / poww(x, abs(n));
return poww(x, n);
}
This code is giving time limit exceed error but when I change the right shift operator >> with normal division operator, the code works just fine.
Working code with division operator
double poww(double x, int n)
{
if (n == 0)
return 1;
double ans = 1;
double temp = x;
while (n)
{
if (n & 1)
{
ans *= temp;
}
temp *= temp;
n /= 2;
}
return ans;
}
double myPow(double x, int n)
{
if (n == 0)
return 1.0;
if (n < 0)
return 1 / poww(x, abs(n));
return poww(x, n);
}
I don't know what I'm missing here.
The problem is the given input range for "n".
Let us look at the constraints again:
The problem is the smallest number for n, which is -2^31 and that is equal to -2147483648.
But the valid range for an integer is -2^31 ... 2^31-1 which is -2147483648 ... 2147483647.
Then you try to use the abs function on -2147483648. But since there is no positive equivalent for that in the integer domain (on your machine), the number stays negative. And then you get the wrong result, because your n will be negative in your "poww" function.
Presumably on your machine long is the same as int, so, a 4 byte variable. If you change your interface to use a long long variable, it will work. Result maybe "inf" for big numbers or 0.
Please check the below code:
#include <iostream>
#include <cmath>
long double poww(double x, long long n)
{
if (n == 0)
return 1;
long double ans = 1;
long double temp = x;
while (n)
{
if (n & 1)
{
ans *= temp;
}
temp *= temp;
n = (n >> 1);
}
return ans;
}
long double myPow(double x, long long n)
{
if (n == 0)
return 1.0;
if (n < 0)
return 1 / poww(x, std::llabs(n));
return poww(x, n);
}
int main() {
std::cout << myPow(1, -2147483648) << '\n';
}

I have a question I have been trying on LeetCode and needed help in the error which is Time Limit exceeded

The link to the particular question is as follows: https://leetcode.com/problems/nth-magical-number/. My code is showing "Time Limit Exceeded" and I cannot figure out where actually lies the error in my code. My code is as follows:
class Solution {
public:
typedef unsigned int ull;
int gcd(int A,int B)
{
if(B==0)
return A;
else
return gcd(B,A%B);
}
int nthMagicalNumber(int N, int A, int B) {
ull m;
if(A<B)
{
int t;
t=A;
A=B;
B=t;
}
ull lcm=(A*B)/gcd(A,B);
ull l=2;
ull h=1e9;
ull n;
while(l<=h)
{
m=l+(h-1)/2;
n=(m/A)+(m/B)-(m/lcm);
if(n==N)
break;
else if(n<N)
l=m+1;
else if(n>N)
h=m-1;
}
ull x=(1e9)+7;
return (int)(m%x);
}
};
Can someone let me know where I am wrong and how can I correct the error?
You might want to use a debugger for that. This solution is just very similar (using Binary Search with gcd) and would pass through:
// This block might trivially optimize the exec time;
// Can be removed;
const static auto __optimize__ = []() {
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
return 0;
}();
#include <cstdint>
#include <vector>
const static struct Solution {
using SizeType = std::uint_fast64_t;
static constexpr SizeType kMod = 1e9 + 7;
const SizeType nthMagicalNumber(
const SizeType N,
const SizeType A,
const SizeType B
) {
const SizeType lowest_common_multiple = A * B / getGreatestCommonDivisor(A, B);
SizeType lo = 2;
SizeType hi = 1e14;
while (lo < hi) {
SizeType mid = lo + (hi - lo) / 2;
if (mid / A + mid / B - mid / lowest_common_multiple < N) {
lo = mid + 1;
} else {
hi = mid;
}
}
return lo % kMod;
}
// __gcd(a, b)
static const SizeType getGreatestCommonDivisor(
const SizeType a,
const SizeType b
) {
if (not b) {
return a;
}
return getGreatestCommonDivisor(b, a % b);
}
};
Instead of ull, here we are using std::uint_fast64_t.
References
For additional details, please see the Discussion Board which you can find plenty of well-explained accepted solutions in there, with a variety of languages including efficient algorithms and asymptotic time/space complexity analysis1, 2.
You can try this approach in C++ for that question my solution got accepted:
class Solution {
public:
long long gcd(long long a, long long b) {
if(b == 0)
return a;
return gcd(b, a % b);
}
int nthMagicalNumber(long long n, long long a, long long b) {
long long end = max(a, b) * (n + 1);
long long min = 1;
long long lcm = (a / gcd(a, b)) * b;
long long curr, mid;
while(min <= end) {
mid = (end - min)/2 + min;
curr = (mid / a) + (mid / b) - (mid / lcm);
if(curr > n) {
end = mid - 1;
} else if(curr < n) {
min = mid + 1;
} else {
break;
}
}
while((mid % a != 0) && (mid % b != 0)) {
mid--;
}
return mid % (1000000007);
}
};

Calculate (a^b)%c where 0<=a,b,c<=10^18

How can I calculate (a ^ b) % c, where 0 <= a, b, c <= 10^18.
Here, (a ^ b) means a to the power b, not a xor b.
My current code for the problem is:
unsigned long long bigMod(unsigned long long b,
unsigned long long p,
unsigned long long m){
if(b == 1) return b;
if(p == 0) return 1;
if(p == 1) return b;
if(p % 2 == 0){
unsigned long long temp = bigMod(b, p / 2ll, m);
return ((temp) * (temp) )% m;
}else return (b * bigMod(b, p-1, m)) % m;
}
For this input:
a = 12345 b = 123456789 and c = 123456789012345
the expected output should be:
59212459031520
You have a problem with temp*temp (long long overflow). You can omit this problem using algorithm of fast mod power to multiply them mod m. Here You have working code:
unsigned long long bigMultiply(unsigned long long b,unsigned long long p, unsigned long long m)
{
if(p == 0 )return b;
if(p%2 == 0)
{
unsigned long long temp = bigMultiply(b,p/2ll,m);
return ((temp)+(temp))%m;
}
else
return (b + bigMultiply(b,p-1,m))%m;
}
unsigned long long bigMod(unsigned long long b,unsigned long long p, unsigned long long m)
{
if(b == 1)
return b;
if(p == 0 )return 1;
if( p == 1)return b;
if(p%2 == 0)
{
unsigned ll temp = bigMod(b,p/2ll,m);
return bigMultiply(temp,temp,m);
}
else
return (b * bigMod(b,p-1,m))%m;
}
I use this code in c++:
long long power(long long a, long long b, long long c)
{
if (b==0)
{
return 1;
}
if (b % 2 == 0)
{
long long w = power(a, b/2, c);
return (w*w) % c;
}
else
{
int w = power(a, b-1, c);
return (a*w) % c;
}
}
It has logarithmic complexity.

Pow function calculation by dynamic programming

I know that pow(base, power) is a built-in function in C with complexity O(power). Can I reduce the complexity of it by dynamic programming?
You can calculate it in O(logn)
int power(int x, unsigned int y)
{
int temp;
if( y == 0)
return 1;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
Details in Here
If your input arguments are non-negative integers, then you can implement your own pow.
Iteratively, with running time = O(n):
unsigned long long pow(unsigned long long x,unsigned int n)
{
unsigned long long res = 1;
while (n--)
res *= x;
return res;
}
Recursively, with running time = O(n):
unsigned long long pow(unsigned long long x,unsigned int n)
{
if (n == 0)
return 1;
if (n == 1)
return x;
return pow(x,n/2)*pow(x,n-n/2);
}
Efficiently, with running time = O(log(n)):
unsigned long long pow(unsigned long long x,unsigned int n)
{
unsigned long long res = 1;
while (n > 0)
{
if (n & 1)
res *= x;
n >>= 1;
x *= x;
}
return res;
}

nCk modulo p when n % p or k % p == 0

I'm trying to solve a coding challenge on hacker rank which requires one to calculate binomial coefficients mod a prime, i.e.
nchoosek(n, k, p)
I'm using the code from this answer that works for the first three sets of inputs but begins failing on the 4th. I stepped through it in the debugger and determined that the issue arises when:
n % p == 0 || k % p == 0
I just need to know how to modify my current solution to handle the specific cases where n % p == 0 or k % p == 0. None of the answers I've found on stack exchange seem to address this specific case. Here's my code:
#include <iostream>
#include <fstream>
long long FactorialExponent(long long n, long long p)
{
long long ex = 0;
do
{
n /= p;
ex += n;
}while(n > 0);
return ex;
}
unsigned long long ModularMultiply(unsigned long long a, unsigned long long b, unsigned long p) {
unsigned long long a1 = (a >> 21), a2 = a & ((1ull << 21) - 1);
unsigned long long temp = (a1 * b) % p; // doesn't overflow under the assumptions
temp = (temp << 21) % p; // this neither
temp += (a2 * b) % p; // nor this
return temp % p;
}
unsigned long long ModularInverse(unsigned long long k, unsigned long m) {
if (m == 0) return (k == 1 || k == -1) ? k : 0;
if (m < 0) m = -m;
k %= m;
if (k < 0) k += m;
int neg = 1;
unsigned long long p1 = 1, p2 = 0, k1 = k, m1 = m, q, r, temp;
while(k1 > 0) {
q = m1 / k1;
r = m1 % k1;
temp = q*p1 + p2;
p2 = p1;
p1 = temp;
m1 = k1;
k1 = r;
neg = !neg;
}
return neg ? m - p2 : p2;
}
// Preconditions: 0 <= k <= min(n,p-1); p > 1 prime
unsigned long long ChooseModTwo(unsigned long long n, unsigned long long k, unsigned long p)
{
// reduce n modulo p
n %= p;
// Trivial checks
if (n < k) {
return 0;
}
if (k == 0 || k == n) {
return 1;
}
// Now 0 < k < n, save a bit of work if k > n/2
if (k > n/2) {
k = n-k;
}
// calculate numerator and denominator modulo p
unsigned long long num = n, den = 1;
for(n = n-1; k > 1; --n, --k)
{
num = ModularMultiply(num, n, p);
den = ModularMultiply(den, k, p);
}
den = ModularInverse(den,p);
return ModularMultiply(num, den, p);
}
// Preconditions: 0 <= k <= n; p > 1 prime
long long ChooseModOne(long long n, long long k, const unsigned long p)
{
// For small k, no recursion is necessary
if (k < p) return ChooseModTwo(n,k,p);
unsigned long long q_n, r_n, q_k, r_k, choose;
q_n = n / p;
r_n = n % p;
q_k = k / p;
r_k = k % p;
choose = ChooseModTwo(r_n, r_k, p);
// If the exponent of p in choose(n,k) isn't determined to be 0
// before the calculation gets serious, short-cut here:
// if (choose == 0) return 0;
return ModularMultiply(choose, ChooseModOne(q_n, q_k, p), p);
}
unsigned long long ModularBinomialCoefficient(unsigned long long n, unsigned long long k, const unsigned long p)
{
// We deal with the trivial cases first
if (k < 0 || n < k) return 0;
if (k == 0 || k == n) return 1;
// Now check whether choose(n,k) is divisible by p
if (FactorialExponent(n, p) > FactorialExponent(k, p) + FactorialExponent(n - k, p)) return 0;
// If it's not divisible, do the generic work
return ChooseModOne(n, k, p);
}
int main() {
//std::ifstream fin ("input03.txt");
std::ifstream fin ("test.in");
int kMod = 1000003;
int T;
fin >> T;
int N = T;
//std::cin >> T;
unsigned long long n, k;
unsigned long long a, b;
int result[N];
int index = 0;
while (T--) {
fin >> n >> k;
a = ModularBinomialCoefficient(n - 3, k, kMod);
b = ModularBinomialCoefficient(n + k, n - 1, kMod);
// (1 / (n + k) * nCk(n - 3, k) * nCk(n + k, n - 1)) % 1000003
unsigned long long x = ModularMultiply(a, b, kMod);
unsigned long long y = ModularMultiply(x, ModularInverse((n + k), kMod), kMod);
result[index] = y;
index++;
}
for(int i = 0; i < N; i++) {
std::cout << result[i] << "\n";
}
return 0;
}
Input:
6
90 13
65434244 16341234
23424244 12341234
424175 341198
7452123 23472
56000168 16000048
Output:
815483
715724
92308
903465
241972
0 <-- Incorrect, should be: 803478
Constraints:
4 <= N <= 10^9
1 <= K <= N
You can use Lucas' theorem to reduce the problem to ceil(log_P(N)) subproblems with k, n < p: Write n = n_m * p^m + ... + n_0 and k = k_m * p^m + ... + k_0 in base p (n_i, k_i < p are the digits), then we have
C(n,k) = PROD(i = 0 to m, C(n_i, k_i)) (mod p)
The subproblems are easy to solve, because every factor of k! has an inverse modulo p. You get an algorithm with runtime complexity O(p log(n)), which is better than that of Ivaylo's code in case of p << n, if I understand it correctly.
int powmod(int x, int e, int p) {
if (e == 0) return 1;
if (e & 1) return (long long)x * powmod(x, e - 1, p) % p;
long long rt = powmod(x, e / 2, p);
return rt * rt % p;
}
int binom_coeff_mod_prime(int n, int k, int p) {
long long res = 1;
while (n || k) {
int N = n % p, K = k % p;
for (int i = N - K + 1; i <= N; ++i)
res = res * i % p;
for (int i = 1; i <= K; ++i)
res = res * powmod(i, p - 2, p) % p;
n /= p;
k /= p;
}
return res;
}
I suggest you use factorization to compute the number of combinations without division. I've got code for doing so here, originally inspired by Fast computation of multi-category number of combinations (I still would like to post a proper answer to that, if some kind souls would reopen it).
My code stores the result as a table of factors, doing the modular multiplication to expand the result should be quite straightforward.
Probably not practical for n in the range of 10**9, though, since the sieve will be quite massive and take a while to construct.