Este es un problema de la sesión de práctica del Concurso de Programación Universitaria de Polonia 2012 . Aunque pude encontrar las soluciones para el concurso principal, parece que no puedo encontrar la solución para este problema en ninguna parte.
El problema es: dado un conjunto de enteros positivos distintos no mayores que , encuentre el tamaño del subconjunto más pequeño que no tenga un divisor común que no sea 1. es como máximo 500, y se puede suponer que existe una solución.
i ≠ j S g 2 g 3 . . . g 10 g 2 g 3 . . . g 10 ≥ 3 × 5 × 7 × 11 × . . . × 29 = 3234846615 > 10 9 , una contradicción.
Sin embargo, incluso con esto, una fuerza bruta directa es demasiado lenta. ¿Alguien tiene alguna otra idea?
algorithms
number-theory
Wakaka
fuente
fuente
Respuestas:
Este problema es equivalente al siguiente, y es trivial construir reducción en ambos sentidos.
Dada una lista de vectores de bits, encuentre el número mínimo de ellos de modo que0 (∗)
and
todos den como resultado el vector de bits. ( ∗ )Luego mostramos que la cobertura del conjunto se reduce a . Por cubierta de conjunto, quiero decir, dada una lista de conjuntos , encuentre el número mínimo de conjuntos que cubre su unión.S 1 , ... , S k(∗) S1,…,Sk
Ordenamos que los elementos en los conjuntos sean . Sea , donde si , 0 en caso contrario. Tenga en cuenta que esta función es una biyección, por lo que tiene un inverso. f ( S ) = ( 1 - χ a 1 ( S ) , … , 1 - χ a n ( S ) ) χ x ( S ) = 1 x ∈ Sa1,…,anorte F( S) = ( 1 - χun1( S) , … , 1 - χunnorte( S) ) χX( S) = 1 x ∈ S
Ahora, si resolvemos en , y las soluciones son , entonces es la solución para configurar la cobertura.f ( S 1 ) , … , f ( S k ) { f ( S b 1 ) , … , f ( S b m ) } { f - 1 ( S b 1 ) , … , f - 1 ( S b m ) }( ∗ ) F( S1) , … , F( Sk) { f( Ssi1) , … , F( Ssimetro) } { f- 1( Ssi1) , … , F- 1( Ssimetro) }
Por lo tanto, creo que este problema es probar la capacidad de uno para podar el espacio de búsqueda.
fuente
Es posible resolver esto de manera relativamente eficiente calculando todos los gcd de pares, eliminando duplicados y luego recurriendo. Es el acto de eliminar duplicados antes de recurrir lo que lo hace eficiente.
Explicaré el algoritmo con más detalle a continuación, pero primero, ayuda a definir un operador binario . Si son conjuntos de enteros positivos, definaS , T⊗ S,T
Tenga en cuenta quey (en su problema); típicamente, será aún más pequeño de lo que sugiere cualquiera de esos límites, lo que ayuda a que el algoritmo sea eficiente. También tenga en cuenta que podemos calcular conoperaciones de gcd por enumeración simple.El | S ⊗ T | ≤ 10 9 S ⊗ T S ⊗ T | S | × | T ||S⊗T|≤|S|×|T| |S⊗T|≤109 S⊗T S⊗ T El | SEl | × | TEl |
Con esa notación, aquí está el algoritmo. Deje que sea el conjunto de números de entrada. Calcule , luego , luego , y así sucesivamente. Encuentre la más pequeña tal que pero . Entonces sabes que el tamaño del subconjunto más pequeño es . Si también desea generar un ejemplo concreto de dicho subconjunto, manteniendo los punteros hacia atrás puede reconstruir fácilmente dicho conjunto.S 2 = S 1 ⊗ S 1 S 3 = S 1 ⊗ S 2 S 4 = S 1 ⊗ S 3 k 1 ∈ S k 1 ∉ S k - 1 kS1 S2= S1⊗ S1 S3= S1⊗ S2 S4 4= S1⊗ S3 k 1 ∈ Sk 1 ∉ Sk - 1 k
Esto será relativamente eficiente, ya que ninguno de los conjuntos intermedios crece en tamaño por encima de (de hecho, su tamaño probablemente será mucho más pequeño que eso), y el tiempo de ejecución requiere aproximadamente operaciones gcd. 500 × ( | S 1 | + | S 2 | + ⋯ )109 9 500 × ( | S1El | + | S2El | +⋯)
Aquí hay una optimización que podría mejorar aún más la eficiencia. Básicamente, puede usar la duplicación iterada para encontrar la más pequeña de manera que . En particular, para cada elemento , hacemos un seguimiento del subconjunto más pequeño de cuyo mcd es y cuyo tamaño es . (Cuando elimina duplicados, resuelve los vínculos a favor del subconjunto que es más pequeño). Ahora, en lugar de calcular la secuencia de nueve conjuntos , calculamos la secuencia de cinco conjuntos , calculando , luego , luego1 ∈ S k x ∈ S i S 1 x ≤ i S 1 , S 2 , S 3 , S 4 , … , S 9 S 1 , S 2 , S 4 , S 8 , S 9 S 2 = S 1 ⊗ S 1 S 4 = S 2 ⊗ S 2 Sk 1∈Sk x∈Si S1 x ≤i S1,S2,S3,S4,…,S9 S1,S2,S4,S8,S9 S2=S1⊗S1 S4=S2⊗S2 S 9 = S 1 × S 8 k ∈ [ 1 , 2 , 4 , 8 , 9 ] 1 ∈ S k k 1 ∈ S k 1 1 S k 1 ∈ S kS8=S4⊗S4 , luego . A medida que avanza, encuentre la primera tal que . Una vez que haya encontrado tal que , puede detenerse de inmediato: puede encontrar el subconjunto más pequeño cuyo mcd es mirando el subconjunto asociado con . Por lo tanto, puede detenerse tan pronto como llegue a un conjunto tal que , lo que le permite detenerse temprano si encuentra un subconjunto más pequeño.S9=S1×S8 k∈[1,2,4,8,9] 1∈Sk k 1∈Sk 1 1 Sk 1∈Sk
Esto debería ser eficiente en el tiempo y en el espacio. Para ahorrar espacio, para cada elemento , no necesita almacenar todo el conjunto: es suficiente para almacenar dos backpointers (por lo que los dos elementos de que tomó el mcd, para obtener ) y opcionalmente el tamaño del subconjunto correspondiente.S i , S j xx∈Sk Si,Sj x
En principio, puede reemplazar la secuencia por cualquier otra cadena de adición . No sé si alguna otra cadena de adición será mejor. La elección óptima podría depender de la distribución de las respuestas correctas y los tamaños esperados de los conjuntos , lo cual no es claro para mí, pero probablemente puede derivarse empíricamente a través de la experimentación.S k[1,2,4,8,9] Sk
Créditos: Mi agradecimiento a KWillets por la idea de almacenar un subconjunto de números junto con cada elemento de , lo que permite parar antes.Si
fuente
Quizás es más rápido ver esto de otra manera ... el primo más grande menor que es 31607, para un recuento total de 3401 primos entre 2 y 31607, no un número muy grande. Escriba cada uno de los números que se le da con factores completos sobre los números primos hasta 31607: Aquí es 1 o un primo grande. Entonces, un conjunto de es relativamente primo si los vectores correspondientes son linealmente independientes (y sus s son diferentes o ambos 1), y está buscando el rango de una matriz. ai=p n i 1 1 p n i 2 2 …PiPiainijP109−−−√
fuente
Si puede encontrar un subconjunto con gcd (S) = 1, siempre puedo eliminar elementos redundantes del subconjunto hasta que solo queden 2 elementos, que tienen gcd (S) = 1. Por lo tanto, puedo afirmar que el más pequeño El subconjunto contendrá 2 elementos o no existirá.
Ahora, usamos la recursividad para resolver este problema. Dividamos la matriz de números en 2 partes, una con n-1 elementos y otra con 1 elemento (último elemento). O bien los 2 números estarán en los primeros n-1 elementos o un elemento estará allí desde la primera parte emparejado con el último elemento. Por lo tanto, podemos resolver este problema en
T (n) = T (n-1) + O (n) tiempo. lo que significa T (n) = O (n ^ 2).
fuente