Mi problema. Dado , quiero contar el número de conjuntos múltiples válida . Un multiset es válido si
- La suma de los elementos de es , y
- Cada número de a se puede expresar de forma única como una suma de algunos de los elementos de .
Ejemplo. Por ejemplo, si entonces son válidos.
Sin embargo, no es válido porque 2 puede estar formado por ambos y (es decir, 2 puede expresarse como y ), por lo que la segunda condición no se cumple. Del mismo modo, 3 pueden estar formados por y .
} también es inválido porque todos los números del al pueden hacer de manera única, pero la suma de los elementos de no es .
He intentado encontrar un buen algoritmo para este problema durante bastante tiempo, pero no puedo resolverlo. Es de codechef . He visto algunas de las soluciones enviadas, pero todavía no pude obtener la lógica para resolver el problema. NOTA: El límite de tiempo para la pregunta es de 10 segundos
Para un conjunto la notación si , lo que significa que ocurre veces en el conjunto múltiple S.a i < a j i < j a i c i
Hasta ahora he sacado algunas conclusiones
- El primer elemento del conjunto múltiple ordenado requerido debe ser
- Deje sea un conjunto que siga las dos propiedades y luego ∀ r < k a r + 1 = a r o ( ∑ r i = 0 a i ) + 1
- Deje , donde ocurre veces, sigue las propiedades requeridas y luego de la conclusión anterior podemos decir que y si .
Prueba:a i c i ∀ i a i | n + 1 a i | a j j > i a i + 1 =
- Ahora considere es decir, todos los números posteriores después de 1 serán un múltiplo de . Deje que sea el recuento de tal multiset posible, entonces donde estoy sumando todos los posibles números de ( ). En otros términosd f ( n ) f ( n ) = ∑ d | n + 11′s=d-1f(n-1)=g(n)=∑d| n,d≠ng(d)
Finalmente, mi problema se reduce a esto: encuentre de manera eficiente para que no exceda el límite de tiempo.
fuente
Respuestas:
Esto es lo que está haciendo la solución más rápida . De hecho, está calculando su función Dado , lo factorizamos (ver a continuación) y luego calcule todos los factores (ver a continuación) en algún orden tal que implique (propiedad P). Ahora calculamos acuerdo con la fórmula al repasar los factores en el orden dado. La propiedad P asegura que cuando calculamos , ya hemos calculado para todos los factores no triviales de . También hay una optimización (ver más abajo).n f 1 , … , f m f i | f j i ≤ j g g ( d ) g ( e ) e d
En más detalle, revisamos los factores en orden, y para cada factor , encontramos todos sus factores no triviales al verificar cuál de divide .f 1 , … , f i - 1 f ifi f1,…,fi−1 fi
Factoring: preprocesamiento: hacemos una lista de todos los primos por debajo de utilizando el tamiz de Eratóstenes. Dado , simplemente usamos la división de prueba. n109 n
Generando todos los factores: esto se hace de forma recursiva. Supongamos que . Corremos anidada bucles , y la salida . Puede probar la propiedad P por inducción. t l 1 ∈ { 0 , ... , k 1 } , ... , l t ∈ { 0 , ... , k t } p l 1 1 ⋯ p l t tn=pk11⋯pktt t l1∈{0,…,k1},…,lt∈{0,…,kt} pl11⋯pltt
Optimización: dado que el programa se ejecuta en varias entradas, podemos usar la memorización para ahorrar tiempo en diferentes entradas. Solo memorizamos valores pequeños (hasta ), y esto nos permite almacenar todos los valores memorizados en una matriz. La matriz se inicializa con ceros, por lo que podemos saber qué valores ya se conocen (ya que todos los valores calculados son positivos).105
Si la factorización prima de es , entonces depende solo de , y de hecho solo de la versión ordenada de este vector Cada número por debajo de tiene como máximo factores primos (con repetición), y dado que , parece factible calcular (o más bien ) para todos ellos, de forma recursiva. Esta solución podría ser más rápida si hubiera muchas entradas diferentes; tal como están las cosas, hay como máximo .p k 1 1 , … , p k t t f ( n ) ( k 1 , … , k t ) 10 9 29 p ( 29 ) = 4565 f g 10n+1 pk11,…,pktt f(n) (k1,…,kt) 109 29 p(29)=4565 f g 10
También es posible que esta función, que asigna particiones a la correspondiente , tenga una forma analítica explícita. Por ejemplo, , viene dada por A000670 , y está dada por A005649 o A172109 .g ( p k ) = 2 k - 1 g ( p 1 … p t ) g ( p 2 1 p 2 … p t )g g(pk)=2k−1 g(p1…pt) g(p21p2…pt)
fuente
OK, entonces tiene una relación de recurrencia para (vea el final de su pregunta).g(⋅)
En este punto, parece que un enfoque natural sería escribir el algoritmo recursivo para calcular y aplicar la memorización para no calcular más de una vez. En otras palabras, cuando calcula , la almacena en una tabla hash que asigna ; Si necesita conocer nuevamente en el futuro, puede buscarlo en la tabla hash.g ( i ) g ( i ) i ↦ g ( i ) g ( i )g(n) g(i) g(i) i↦g(i) g(i)
Esto requiere factorizar , pero existen algoritmos eficientes para factorizar cuando .n n ≤ 10 9n n n≤109
También puede buscar la secuencia en la Enciclopedia en línea de secuencias enteras . Si encuentra la secuencia en su enciclopedia, a veces le proporcionarán información útil adicional (por ejemplo, algoritmos eficientes para calcular la secuencia). Sin embargo, eso ciertamente podría quitarle la diversión a las cosas.g(1),g(2),g(3),g(4),g(5),…
fuente
Aquí hay una pista para comenzar. Aplique algoritmos de programación dinámica estándar para enumerar el conjunto de particiones de un número entero y agregue algo de lógica para verificar cuál de ellos permite la realización de cambios únicos al verificar de forma iterativa todas las sumas, realizar cambios y verificar la unicidad.
En un poco más de detalle: supongamos que tiene un varios conjuntos . Dado un número con , ¿cómo podría identificar un subconjunto de que sume a ? ¿Cómo podría verificar si ese submultiset es único? Intente adaptar las técnicas de programación dinámica estándar para realizar cambios . (Ver también esta pregunta ).i 1 ≤ i ≤ n S iS i 1≤i≤n S i
Dado un varios conjuntos , ¿cómo podría verificar si cumple con la segunda condición, es decir, si cada número del 1 al puede expresarse de manera única como la suma de un submultiset de (la condición única de hacer cambios)? Esto debería ser bastante fácil, si resolvió el anterior.n SS n S
deje que denote la lista de multisets que satisfacen ambas condiciones. Si supieras , ¿cómo podrías usar esa información para construir ? Aquí es posible que desee adaptar las técnicas de programación dinámica estándar para enumerar las particiones de un número entero.P(n) P(1),P(2),…,P(n) P(n+1)
Aquí hay un enfoque que probablemente será mejor.
Supongamos que es un conjunto múltiple que satisface ambas condiciones (para ). ¿Cómo podemos extenderlo para obtener una multiset que tiene un elemento más? En otras palabras, ¿cómo podemos identificar todas las formas de agregar un elemento más a , para obtener una nueva multiset que satisfaga ambas condiciones (para algunos )?S n T S T n′
Respuesta: si puede expresarse como una suma de algunos de los elementos de , entonces no tiene sentido agregarlo a : eso causaría que viole la condición de unicidad. Entonces, podemos enumerar todos los enteros que no se pueden expresar como una suma de algunos de los elementos de ; cada uno es algo que podría agregarse potencialmente a para obtener un nuevo multiset que satisfaga ambas condiciones (para algún otro ).x S S T x S S T n
Además, es posible enumerar qué números enteros se pueden expresar como una suma de algunos de los elementos de , y cuáles no, utilizando la programación dinámica. Construye una matriz bidimensional de booleanos, donde es verdadero si hay una manera de expresar el entero como una suma de algunos de los primeros elementos de (solo los primeros elementos de son elegibles para ser utilizados; donde ha sido ordenado, entonces y ). Tenga en cuenta queS A[1…|S|,1…n] A[i,j] j i S i S S S={s1,s2,…,sk} s1≤s2≤⋯≤sk A[i,j] se puede calcular utilizando los valores de : en particular, si , o contrario. Esto nos permite identificar todos los números que son candidatos para ser añadido a .A[1…i−1,1…j−1] A[i,j]=A[i−1,j]∨A[i−1,j−si] j>si A[i,j]=A[i−1,j] S
A continuación, para cada extensión candidata de (obtenida al agregar un elemento a ), queremos verificar si cumple ambas condiciones. Deje denotar la suma de los elementos de , y la suma de los elementos de . Tenemos que comprobar si cada número entero en el rango pueden expresarse como una suma de algunos de los elementos de . Esto también se puede resolver mediante programación dinámica, utilizando algoritmos estándar para la realización de cambios. (De hecho, si todavía tiene la matrizT S S T n S n′ T n+1,n+2,…,n′ T A mencionado anteriormente, puede extenderlo un poco fácilmente para resolver este problema: lo convertimos en una matriz , continuamos completando todas las entradas adicionales y nos aseguramos de que son todos verdaderos.) Entonces, ahora podemos enumerar todos los multisets que se extienden por un solo elemento y que satisfacen ambas condiciones.A[1…|T|,1…n′] T SA[|T|,n+1],A[|T|,n+2],…,A[|T|,n′] T S
Esto sugiere inmediatamente un algoritmo para enumerar todos los conjuntos múltiples que satisfacen su condición, para todos hasta cierto límite, digamos . Tendremos una matriz , donde almacena todos los multisets que suman 5 y, en general, almacena el conjunto de todos los multisets que suman .n n ≤ 20 P [ 1 … 20 ] P [ 5 ] S P [ n ] S nS n n≤20 P[1…20] P[5] S P[n] S n
A continuación, podemos completar iterativa. Comience configurando para que contenga solo un conjunto múltiple . A continuación, para cada (contando de 1 a 20), para cada , enumere todas las posibles extensiones de (usando las técnicas anteriores), denote la suma de los elementos de , e inserte en si aún no está presente y si .P [ 1 ] { 1 } n S ∈ P [ n ] T S n ′ T T P [ n ′ ] n ′ ≤ 20P[n] P[1] {1} n S∈P[n] T S n′ T T P[n′] n′≤20
Esto debería ser bastante factible. ¡Buena suerte! ¡Que te diviertas! Trabajar en los detalles será un buen ejercicio de aprendizaje en programación dinámica.
fuente