I'm trying to solve the equation:
(binomial(n - 3, k, p) * binomial(n + k, n - 1, p) / (n + k)) % 1000003
My current solution:
int a, b, r;
a = BinomialModPrime(n - 3, k, P);
b = BinomialModPrime(n + k, n - 1, P);
r = ModularMultiply(a, b, P);
r = ModularMultiply(r, ModularInverse(n + k, P), P);
was working fine until I got to a problem set where there was no modular inverse for any (n + k) because
(n + k) % 1000003 == 0.
So my question is, is there another way to solve this that doesn't involve multiplication by the modular inverse? For instance, will any of these suggestions work for my problem?
Related
Problem statement: Compute the binonimal coefficient C(n,k) mod p. Here p is a prime.
I've done a bit of research online but I still don't understand why the following code works for this problem:
factorial[0] = 1;
for (int i = 1; i <= MAXN; i++) {//compute factorial
factorial[i] = factorial[i - 1] * i % m;
}
long long binomial_coefficient(int n, int k) {
return factorial[n] * inverse(factorial[k] * factorial[n - k] % m) % m;//I don't get it why we have to multiply with inverse(factorial[k] * factorial[n - k] % m)
}
I know the definition of modular inverse but i'm still confused how it can be relevant here. Can someone help me clarify this code ?
The factorial formula C(n, k) = n! / (k! (n-k)!) can be rewritten as C(n, k) k! (n-k)! = n!. Then:
taking mod p on both sides: C(n, k) k! (n-k)! ≡ n! mod p;
multiplying by the modular inverse: C(n, k) k! (n-k)! inverse(k! (n-k)!) ≡ n! inverse(k! (n-k)!) mod p;
simplifying a inv(a) = 1: C(n, k) ≡ n! inverse(k! (n-k)!) mod p.
The latter is equivalent to C(n, k) mod p = ((n! mod p) (inverse(k! (n-k)!) mod p)) mod p.
I want to compute nCk mod m with following constraints:
n<=10^18
k<=10^5
m=10^9+7
I have read this article:
Calculating Binomial Coefficient (nCk) for large n & k
But here value of m is 1009. Hence using Lucas theorem, we need only to calculate 1009*1009 different values of aCb where a,b<=1009
How to do it with above constraints.
I cannot make a array of O(m*k) space complexity with given constraints.
Help!
The binominal coefficient of (n, k) is calculated by the formula:
(n, k) = n! / k! / (n - k)!
To make this work for large numbers n and k modulo m observe that:
Factorial of a number modulo m can be calculated step-by-step, in
each step taking the result % m. However, this will be far too slow with n up to 10^18. So there are faster methods where the complexity is bounded by the modulo, and you can use some of those.
The division (a / b) mod m is equal to (a * b^-1) mod m, where b^-1 is the inverse of b modulo m (that is, (b * b^-1 = 1) mod m).
This means that:
(n, k) mod m = (n! * (k!)^-1 * ((n - k)!)^-1) mod m
The inverse of a number can be efficiently found using the Extended Euclidean algorithm. Assuming you have the factorial calculation sorted out, the rest of the algorithm is straightforward, just watch out for integer overflows on multiplication. Here's reference code that works up to n=10^9. To handle for larger numbers the factorial computation should be replaced with a more efficient algorithm and the code should be slightly adapted to avoid integer overflows, but the main idea will remain the same:
#define MOD 1000000007
// Extended Euclidean algorithm
int xGCD(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1, gcd = xGCD(b, a % b, x1, y1);
x = y1;
y = x1 - (long long)(a / b) * y1;
return gcd;
}
// factorial of n modulo MOD
int modfact(int n) {
int result = 1;
while (n > 1) {
result = (long long)result * n % MOD;
n -= 1;
}
return result;
}
// multiply a and b modulo MOD
int modmult(int a, int b) {
return (long long)a * b % MOD;
}
// inverse of a modulo MOD
int inverse(int a) {
int x, y;
xGCD(a, MOD, x, y);
return x;
}
// binomial coefficient nCk modulo MOD
int bc(int n, int k)
{
return modmult(modmult(modfact(n), inverse(modfact(k))), inverse(modfact(n - k)));
}
Just use the fact that
(n, k) = n! / k! / (n - k)! = n*(n-1)*...*(n-k+1)/[k*(k-1)*...*1]
so you actually have just 2*k=2*10^5 factors. For the inverse of a number you can use suggestion of kfx since your m is prime.
First, you don't need to pre-compute and store all the possible aCb values! they can be computed per case.
Second, for the special case when (k < m) and (n < m^2), the Lucas theorem easily reduces to the following result:
(n choose k) mod m = ((n mod m) choose k) mod m
then since (n mod m) < 10^9+7 you can simply use the code proposed by #kfx.
We want to compute nCk (mod p). I'll handle when 0 <= k <= p-2, because Lucas's theorem handles the rest.
Wilson's theorem states that for prime p, (p-1)! = -1 (mod p), or equivalently (p-2)! = 1 (mod p) (by division).
By division: (k!)^(-1) = (p-2)!/(k!) = (p-2)(p-3)...(k+1) (mod p)
Thus, the binomial coefficient is n!/(k!(n-k)!) = n(n-1)...(n-k+1)/(k!) = n(n-1)...(n-k+1)(p-2)(p-3)...(k+1) (mod p)
Voila. You don't have to do any inverse computations or anything like that. It's also fairly easy to code. A couple optimizations to consider: (1) you can replace (p-2)(p-3)... with (-2)(-3)...; (2) nCk is symmetric in the sense that nCk = nC(n-k) so choose the half that requires you to do less computations.
I want to compute nCk mod m with following constraints:
n<=10^18
k<=10^5
m=10^9+7
I have read this article:
Calculating Binomial Coefficient (nCk) for large n & k
But here value of m is 1009. Hence using Lucas theorem, we need only to calculate 1009*1009 different values of aCb where a,b<=1009
How to do it with above constraints.
I cannot make a array of O(m*k) space complexity with given constraints.
Help!
The binominal coefficient of (n, k) is calculated by the formula:
(n, k) = n! / k! / (n - k)!
To make this work for large numbers n and k modulo m observe that:
Factorial of a number modulo m can be calculated step-by-step, in
each step taking the result % m. However, this will be far too slow with n up to 10^18. So there are faster methods where the complexity is bounded by the modulo, and you can use some of those.
The division (a / b) mod m is equal to (a * b^-1) mod m, where b^-1 is the inverse of b modulo m (that is, (b * b^-1 = 1) mod m).
This means that:
(n, k) mod m = (n! * (k!)^-1 * ((n - k)!)^-1) mod m
The inverse of a number can be efficiently found using the Extended Euclidean algorithm. Assuming you have the factorial calculation sorted out, the rest of the algorithm is straightforward, just watch out for integer overflows on multiplication. Here's reference code that works up to n=10^9. To handle for larger numbers the factorial computation should be replaced with a more efficient algorithm and the code should be slightly adapted to avoid integer overflows, but the main idea will remain the same:
#define MOD 1000000007
// Extended Euclidean algorithm
int xGCD(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1, gcd = xGCD(b, a % b, x1, y1);
x = y1;
y = x1 - (long long)(a / b) * y1;
return gcd;
}
// factorial of n modulo MOD
int modfact(int n) {
int result = 1;
while (n > 1) {
result = (long long)result * n % MOD;
n -= 1;
}
return result;
}
// multiply a and b modulo MOD
int modmult(int a, int b) {
return (long long)a * b % MOD;
}
// inverse of a modulo MOD
int inverse(int a) {
int x, y;
xGCD(a, MOD, x, y);
return x;
}
// binomial coefficient nCk modulo MOD
int bc(int n, int k)
{
return modmult(modmult(modfact(n), inverse(modfact(k))), inverse(modfact(n - k)));
}
Just use the fact that
(n, k) = n! / k! / (n - k)! = n*(n-1)*...*(n-k+1)/[k*(k-1)*...*1]
so you actually have just 2*k=2*10^5 factors. For the inverse of a number you can use suggestion of kfx since your m is prime.
First, you don't need to pre-compute and store all the possible aCb values! they can be computed per case.
Second, for the special case when (k < m) and (n < m^2), the Lucas theorem easily reduces to the following result:
(n choose k) mod m = ((n mod m) choose k) mod m
then since (n mod m) < 10^9+7 you can simply use the code proposed by #kfx.
We want to compute nCk (mod p). I'll handle when 0 <= k <= p-2, because Lucas's theorem handles the rest.
Wilson's theorem states that for prime p, (p-1)! = -1 (mod p), or equivalently (p-2)! = 1 (mod p) (by division).
By division: (k!)^(-1) = (p-2)!/(k!) = (p-2)(p-3)...(k+1) (mod p)
Thus, the binomial coefficient is n!/(k!(n-k)!) = n(n-1)...(n-k+1)/(k!) = n(n-1)...(n-k+1)(p-2)(p-3)...(k+1) (mod p)
Voila. You don't have to do any inverse computations or anything like that. It's also fairly easy to code. A couple optimizations to consider: (1) you can replace (p-2)(p-3)... with (-2)(-3)...; (2) nCk is symmetric in the sense that nCk = nC(n-k) so choose the half that requires you to do less computations.
There are 3 numbers: T, N, M. 1 ≤ T, M ≤ 10^9, 1 ≤ N ≤ 10^18 .
What is asked in the problem is to compute [Σ(T^i)]mod(m) where i varies from 0 to n. Obviously, O(N) or O(M) solutions wouldn't work because of 1 second time limit. How should I proceed?
As pointed out in previous answers, you may use the formula for geometric progression sum. However there is a small problem - if m is not prime, computing (T^n - 1) / (T - 1) can not be done directly - the division will not be a well-defined operations. In fact there is a solution that can handle even non prime modules and will have a complexity O(log(n) * log(n)). The approach is similar to binary exponentiation. Here is my code written in c++ for this(note that my solution uses binary exponentiation internally):
typedef long long ll;
ll binary_exponent(ll x, ll y, ll mod) {
ll res = 1;
ll p = x;
while (y) {
if (y % 2) {
res = (res * p) % mod;
}
p = (p * p) % mod;
y /= 2;
}
return res;
}
ll gp_sum(ll a, int n, ll mod) {
ll A = 1;
int num = 0;
ll res = 0;
ll degree = 1;
while (n) {
if (n & (1 << num)) {
n &= (~(1 << num));
res = (res + (A * binary_exponent(a, n, mod)) % mod) % mod;
}
A = (A + (A * binary_exponent(a, degree, mod)) % mod) % mod;
degree *= 2;
num++;
}
return res;
}
In this solution A stores consecutively the values 1, 1 + a, 1 + a + a^2 + a^3, ...1 + a + a^2 + ... a ^ (2^n - 1).
Also just like in binary exponentiation if I want to compute the sum of n degrees of a, I split n to sum of powers of two(essentially using the binary representation of n). Now having the above sequence of values for A, I choose the appropriate lengths(the ones that correspond to 1 bits of the binary representation of n) and multiply the sum by some value of a accumulating the result in res. Computing the values of A will take O(log(n)) time and for each value I may have to compute a degree of a which will result in another O(log(n)) - thus overall we have O(log(n) * log (n)).
Let's take an example - we want to compute 1 + a + a^2 .... + a ^ 10. In this case, we call gp_sum(a, 11, mod).
On the first iteration n & (1 << 0) is not zero as the first bit of 11(1011(2)) is 1. Thus I turn off this bit setting n to 10 and I accumulate in res: 0 + 1 * (a ^ (10)) = a^10. A is now a + 1.
The next second bit is also set in 10(1010(2)), so now n becomes 8 and res is a^10 + (a + 1)*(a^8)=a^10 + a^9 + a^8. A is now 1 + a + a^2 + a^3
Next bit is 0, thus res stays the same, but A will become 1 + a + a^2 + ... a^7.
On the last iteration the bit is 1 so we have:
res = a^10 + a^9 + a^8 + a^0 *(1 + a + a^2 + ... +a^7) = 1 + a .... + a ^10.
One can use an algorithm which is similar to binary exponentiation:
// Returns a pair <t^n mod m, sum of t^0..t^n mod m>,
// I assume that int is big enough to hold all values without overflowing.
pair<int, int> calc(int t, int n, int m)
if n == 0 // Base case. t^0 is always 1.
return (1 % m, 1 % m)
if n % 2 == 1
// We just compute the result for n - 1 and then add t^n.
(prevPow, prevSum) = calc(t, n - 1, m)
curPow = prevPow * t % m
curSum = (prevSum + curPow) % m
return (curPow, curSum)
// If n is even, we compute the sum for the first half.
(halfPow, halfSum) = calc(t, n / 2, m)
curPow = halfPow * halfPow % m // t^n = (t^(n/2))^2
curSum = (halfSum * halfPow + halfSum) % m
return (curPow, curSum)
The time complexity is O(log n)(the analysis is the same as for the binary exponentiation algorithm). Why is it better than a closed form formula for geometric progression? The latter involves division by (t - 1). But it is not guaranteed that there is an inverse of t - 1 mod m.
you can use this:
a^1 + a^2 + ... + a^n = a(1-a^n) / (1-a)
so, you just need to calc:
a * (1 - a^n) / (1 - a) mod M
and you can find O(logN) way to calc a^n mod M
It's a geometric series whose sum is equal to :
I want to calculate multinomial coefficient mod 1e9 + 7. It equals: n! / (k0! * k1! * k2 * ... * km!)
In my case m = 3, k0 + k1 + k2 = n, so it would be: n! / (k0! * k1! * k2!) My code for this:
....
long long k2 = n - k1 - k0;
long long dans = fact[n] % MOD;
long long tmp = fact[i] % MOD;
tmp = (tmp * fact[j]) % MOD;
tmp = (tpm * fact[k]) % MOD;
res = (fact[n] / tmp) % MOD; // mb mistake is here...
cout << res;
fact[i] - factorial of i mod 1e9+7
It does not work on big tests
I hope I'm not linkfarming here, but here is a process of work, to solve your problem :
Naive implementations will always suffer from overflow errors. You have to be ready to exploit certain mathematical properties of the polynomial coefficient to reach a robust solution. Dave Barber does that in his library, where the recursive property is used (example for 4 numbers - the recursion stops when all branches are replaced by zero)
multi (a, b, c, d) = multi (a − 1, b, c, d) + multi (a, b − 1, c, d) + multi (a, b, c − 1, d) + multi (a, b, c, d − 1)
Based on the above, David Serrano Martínez shows how an implementation that provides overflow control can be divised. His code can be used as easily as
unsigned long long result_2 = multinomial::multi<unsigned long long>({9, 8, 4});
A third alternative would be to use (or learn from) libraries that are dedicated to combinatorics, like SUBSET. This is a bit more difficult code to read through due to dependencies and length, but invokation is as easy as
int factors[4] = {1, 2, 3, 4};
Maths::Combinatorics::Arithmetic::multinomial(4, factors)
You can calculate by multiplying the numerator down from sum(ks) and dividing up in the denominator up from 1. The result as you progress will always be integers, because you divide by i only after you have first multiplied together i contiguous integers.
def multinomial(*ks):
""" Computes the multinomial coefficient of the given coefficients
>>> multinomial(3, 3)
20
>>> multinomial(2, 2, 2)
90
"""
result = 1
numerator = sum(ks)
ks = list(ks) # These two lines are unnecessary optimizations
ks.remove(max(ks)) # and can be removed
for k in ks:
for i in range(k):
result *= numerator
result //= i + 1
numerator -= 1
return result
I recently came across this problem, and my solution was to first map to log-space, do the work there, and then map back. This is helpful as we avoid the overflow issues in log-space, and also multiplications become sums which can be more efficient. It may also be useful to work directly with the log-space result.
The maths:
C(x1, ..., xn) = sum(x)! / (x1! * ... * xn!)
Therefore
ln C(x1, ..., xn) = ln sum(x)! - ln {(x1! * ... * xn!)}
= sum{k=1->sum(x)} ln k - sum(ln xi!)
= sum{k=1->sum(x)} ln k - sum(sum{j=1->xi} (ln j))
If any of the xi, or sum(x) are big (e.g. > 100), then we could actually just use Sterling's approximation:
ln x! ~= x * ln x - x
Which would give:
ln C(x1, ..., xn) ~= sum(x) * ln sum(x) - sum(x) - sum(xi * ln xi - xi)
Here's the code. It's helpful to first write a log factorial helper function.
#include <vector>
#include <algorithm> // std::transform
#include <numeric> // std::iota, std:: accumulate
#include <cmath> // std::log
#include <type_traits> // std::enable_if_t, std::is_integral, std::is_floating_point
template <typename RealType, typename IntegerType,
typename = std::enable_if_t<std::is_floating_point<RealType>::value>,
typename = std::enable_if_t<std::is_integral<IntegerType>::value>>
RealType log_factorial(IntegerType x)
{
if (x == 0 || x == 1) return 0;
if (x == 2) return std::log(2); // can add more for efficiency
if (x > 100) {
return x * std::log(x) - x; // Stirling's approximation
} else {
std::vector<IntegerType> lx(x);
std::iota(lx.begin(), lx.end(), 1);
std::vector<RealType> tx(x);
std::transform(lx.cbegin(), lx.cend(), tx.begin(),
[] (IntegerType a) { return std::log(static_cast<RealType>(a)); });
return std::accumulate(tx.cbegin(), tx.cend(), RealType {});
}
}
Then the log factorial function is simple:
template <typename RealType, typename IntegerType>
RealType log_multinomial_coefficient(std::initializer_list<IntegerType> il)
{
std::vector<RealType> denoms(il.size());
std::transform(il.begin(), il.end(), denoms.begin(), log_factorial<RealType, IntegerType>);
return log_factorial<RealType>(std::accumulate(il.begin(), il.end(), IntegerType {})) -
std::accumulate(denoms.cbegin(), denoms.cend(), RealType {});
}
And finally the multinomial coefficient method:
template <typename RealType, typename IntegerType>
IntegerType multinomial_coefficient(std::initializer_list<IntegerType> il)
{
return static_cast<IntegerType>(std::exp(log_multinomial_coefficient<RealType, IntegerType>(std::move(il))));
}
e.g.
cout << multinomial_coefficient<double, long long>({6, 3, 3, 5}) << endl; // 114354240
For any inputs much greater than this we are going to overflow with built in types, but we can still obtain the log-space result, e.g.
cout << log_multinomial_coefficient<double>({6, 3, 11, 5, 10, 8}) << endl; // 65.1633
Wiki Page
You can Implement this method :
Here's what I came up with in Python --
from math import comb
def Multinomial_Coefficient(R:list|tuple):
# list R is assumed to be summing up to n
Ans = 1
for i in range(len(R)):
Ans *= comb(sum(R[:i+1]), R[i])
return Ans