Modulo of factorial divided by factorial

Solution 1:

If a, bs and p are fairly small, prefer @KellyBundy's approach of cancelling factors, or counting prime factors.

Multiplication and modular arithmetic

Given integers m and n and some other integer k:

(m * n) modulo k = ((m modulo k) * (n mod k)) modulo k

This allows a large product to be calculated modulo p without worrying about overflow, since we can always keep the arguments in the range [0, k).

For example to compute the factorial a! modulo k, in python:

def fact(a, k):
    if a == 0:
        return 1
    else:
        return ((a % k) * fact(a - 1, k)) % k

Division and modular arithmetic

If p is a prime then for any integer n that is not divisible by p, we can find an integer which I'll call inv(n) such that:

(n * inv(n)) modulo p = 1

This number is called the modular inverse of n. There are various algorithms to find modular inverses, which I won't describe here (but see e.g. here).

Now, given integers n and m, and assuming that m / n is an integer, we can apply the rule:

(m / n) modulo p = (m * inv(n)) modulo p

So provided we can calculate modular inverses, we can convert division to multiplication, and then apply the previous rule.

Solution 2:

Another way, listing the factors 1 to a, then canceling with all divisors, then multiplying modulo p:

#include <iostream>
#include <vector>

int gcd(int a, int b) {
  return b ? gcd(b, a % b) : a;
}

int main() {
  int a = 60;
  std::vector<int> bs = {13, 7, 19};
  int p = 10007;

  std::vector<int> factors(a);
  for (int i=0; i<a; i++)
    factors[i] = i + 1;
  for (int b : bs) {
    while (b > 1) {
      int d = b--;
      for (int& f : factors) {
        int g = gcd(f, d);
        f /= g;
        d /= g;
      }
    }
  }
  int result = 1;
  for (int f : factors)
    result = result * f % p;
  std::cout << result;
}

Prints 5744, same as this Python code:

from math import factorial, prod

a = 60
bs = [13, 7, 19]
p = 10007

num = factorial(a)
den = prod(map(factorial, bs))
print(num // den % p)