una teorema propiedades potencia numeros numero newton los ejemplos demostraciones combinatorios combinatorio coeficiente calculadora binomio binomial algorithm math combinatorics binomial-coefficients

algorithm - teorema - Coeficiente binomial módulo 142857



propiedades de los numeros combinatorios demostraciones (3)

El algoritmo es:

  • factorizar la base en poderes principales; 142857 = 3 ^ 3 × 11 × 13 × 37
  • calcular el módulo de resultado de cada potencia principal
  • combine los resultados usando el Teorema del Remanente chino.

Para calcular (n above k) mod p^q :

Fuente: http://www.dms.umontreal.ca/~andrew/PDF/BinCoeff.pdf , teorema 1

define (n!)_p como el producto de los números 1..n que no son divisibles por p

define n_j como n después de borrar j dígitos menos significativos en la base p

definir r como n - k

define e_j como el número de acarreos cuando se agrega k+r , sin contar los acarreos de j dígitos más bajos, computando en base p

define s como 1 si p=2 & q>=3 y -1 contrario

luego (n above k) mod p^q := p^e_0 * s^e_(q-1) * concatenate(j=d..0)( (n_j!)_p / ((k_j!)_p*(r_j!)_p) ) con cada término de la concatenación que computa un dígito base-p del resultado, el menor j calcula los dígitos menos significativos que no sean cero.

Cómo calcular el coeficiente binomial módulo 142857 para n grande y r . ¿Hay algo especial sobre el 142857? Si la pregunta es modulo p donde p es primo, entonces podemos usar el teorema de Lucas pero lo que debería hacerse para 142857.


Lo especial de 142857 es que 7 * 142857 = 999999 = 10 ^ 6 - 1. Este es un factor que surge del Pequeño Teorema de Fermat con a = 10 yp = 7, produciendo la equivalencia modular 10 ^ 7 == 10 (mod 7 ) Eso significa que puede trabajar con el módulo 999999 en su mayor parte y reducir al módulo final al dividir por 7 al final. La ventaja de esto es que la división modular es muy eficiente en las bases de representación de la forma 10 ^ k para k = 1,2,3,6. Todo lo que haces en estos casos es agregar grupos de dígitos; esta es una generalización de sacar nueves .

Esta optimización solo tiene sentido si tienes multiplicación de hardware base-10. Lo que realmente quiere decir que funciona bien si tienes que hacer esto con papel y lápiz. Dado que este problema apareció recientemente en un concurso en línea, imagino que ese es exactamente el origen de la pregunta.


En realidad puedes calcular C(n,k) % m en el tiempo O(n) para m arbitraria.

El truco es calcular n! , k! y (nk)! como vectores de potencia principal, reste los dos más adelante del primero y multiplique el módulo m restante. Para C(10, 4) hacemos esto:

10! = 2^8 * 3^4 * 5^2 * 7^1 4! = 2^3 * 3^1 6! = 2^4 * 3^2 * 5^1

Por lo tanto

C(10,4) = 2^1 * 3^1 * 5^1 * 7^1

Podemos calcular esto fácilmente mod m ya que no hay divisiones. El truco es calcular la descomposición de n! y amigos en tiempo lineal. Si precalculamos los números primos hasta n , podemos hacerlo de la siguiente manera: Claramente, para cada número par en el producto 1*2*...*9*10 obtenemos un factor de 2 . Para cada cuarto número, obtenemos un segundo y así sucesivamente. De ahí la cantidad de 2 factores en n! es n/2 + n/4 + n/8 + ... (donde / está el piso). Hacemos lo mismo para los primos restantes, y como hay primos O(n/logn) menores que n , y hacemos O(logn) para cada uno, la descomposición es lineal.

En la práctica, lo codificaría más implícito de la siguiente manera:

func Binom(n, k, mod int) int { coef := 1 sieve := make([]bool, n+1) for p := 2; p <= n; p++ { if !sieve[p] { // Sieve of Eratosthenes for i := p*p; i <= n; i += p { sieve[i] = true } // Calculate influence of p on coef for pow := p; pow <= n; pow *= p { cnt := n/pow - k/pow - (n-k)/pow for j := 0; j < cnt; j++ { coef *= p coef %= mod } } } } return coef }

Esto incluye un tamiz de Eratóstenes, por lo que el tiempo de ejecución es nloglogn lugar de n si los primos se han calculado previamente o tamizado con un tamiz más rápido.