4

I'd like to calculate Ps mod K where Ps is the total number of unique permutations of elements in a set S. The problem is, the set S can have repetitions, so Ps = n! / (f1!f2! ... fn!), where n is the number of elements, and denominator the product of factorial of frequencies of each element in S.

The integer n can be assumed significantly large, say around 10^6, and wouldn't likely fit in a uint64_t. Is it even possible to calculate Ps mod K without resorting to an arbitrary precision library? If yes, are there any fast methods to calculate it?

3 Answers3

6

Consider as an example 9!/(4!3!2!). This is

9.8.7.6   5.4.3   2.1
------- x ----- x ---
4.3.2.1   3.2.1   2.1

In other words it is a product of 3 binomial coefficients 9C4 x 5C3 x 2C2. In this way you are always going to be able to reduce it to a product of binomial coefficients. You need to work out these binomial coefficients modulo K and multiply the answers together modulo K.

So you need an efficient way to work out binomial coefficients modulo K.

I don't know how feasible this is for n == 10^6 but a method for efficiently calculating binomial coefficients mod K is given here:

https://fishi.devtail.io/weblog/2015/06/25/computing-large-binomial-coefficients-modulo-prime-non-prime/

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • That's a neat observation! I'm going to get reading that article. I'll get back as soon as I have a working implementation. – Methusael Murmu Oct 04 '15 at 04:10
  • @MethusaelMurmu Good luck. I think it's going to be quite hard - I'd do a detailed search to see if a library does this already. – Paul Boddington Oct 04 '15 at 04:12
  • The blog link got updated: https://fishi.devtail.io/weblog/2015/06/25/computing-large-binomial-coefficients-modulo-prime-non-prime/ – fishi0x01 Jan 13 '19 at 12:07
0

If you want to calculate e.g. n!modK, you don't need to calculate n! first. Instead you could do a loop that looks like this.

result = 1
for(i = 2; i <= n; i++) {
  result = (result * i) % K
}

The easiest way to explain why this works is to look at what happens to the last digit of a number when you multiply it with something else. e.g. 1234 * 3. What is the last digit of the result? It's a 2 which is equal to (4*3)mod10. The last digit of the result is only affected by the last digit of the two factors. That is true in every number system. Not just base 10. Therefore it's sufficient for the variable result to store the last digit of the result in base K.

Tesseract
  • 8,049
  • 2
  • 20
  • 37
  • The problem is that the question involves division. If you know what `n!`, `r!` and `(n - r)!` are modulo `K`, that doesn't tell you the value of `n!/(r! * (n - r)!)` modulo `K` because the denominator might not be an invertible element of the ring of integers modulo `K`. – Paul Boddington Oct 04 '15 at 01:30
0

If there's a need to calculate Ps mod K for many values of Ps, then it might be wise to precompute n! mod K for all values of n that you might need (if n ≤ 106 then that's reasonable).

Also, if K is prime, you can handle division by instead multiplying by the "modular multiplicative inverse" of the number you want to divide by. For instance, if K=1,000,000,007 then instead of dividing by 2 you can multiply by 500,000,004.

There are a few ways to compute it, the easiest one being to calculate xK-2 mod K (this works thanks to Fermat's little theorem). You can then precalculate the modular multiplicative inverse of every factorial as well. Then it's very easy to calculate Ps mod K using the cached values.

Ryan Tarpine
  • 761
  • 7
  • 9