Creo que el hecho de que los números deben tener posiciones distintas es una pista falsa. Puede usar el principio de inclusión-exclusión para contar el número de todas las posiciones (i, j, k, l, m) donde x [i] + x [j] + x [k] + x [l] + x [ m] = S y i, j, k, l, m son distintos:
sums with i!=j,i!=k,i!=l...,l!=m = all sums
- sums with i=j
- ...
- sums with l=m
+ sums with i=j and j=k
+ ...
+ sums with k=l and l=m
- ...
+ sums with i=j=k=l=m
Cálculo de las cantidades a la derecha, excepto la primera, es factible en O (N^2 log N). Por ejemplo, para encontrar el número de posiciones (i, i, k, l, m) tales que x [i] + x [i] + x [k] + x [l] + x [m] = S usted puede crea matrices ordenadas con sumas {2a + b} y {c + d} y comprueba si tienen elementos x, y tales que x + y = S.
algoritmo principal
Así que es suficiente para calcular cuántos hay posiciones (i, j, k, l, m) donde x[i]+x[j]+x[k]+x[l]+x[m]=S
y i, j, k, l, m no son necesariamente diferentes. Básicamente, se puede utilizar la solución de Morón de esta manera:
crear una matriz ordenada de sumas {a + b: a, b son números de serie}; agrupe los elementos iguales en uno, recordando el recuento. Por ejemplo, para la matriz [1,1,3] se obtienen nueve sumas [2,2,2,2,4,4,4,4,6] de la forma a + b. Luego, agrupa los mismos elementos que recuerdan los recuentos: [(2,4), (4,4), (6,1)]. Este paso es O (N^2 log N).
Para cada e, cuente cuántos hay pares de elementos en la matriz que suman a S-e. Como en la solución de Moron, tienes dos indicadores, uno va a la derecha, uno va a la izquierda. Si la suma es demasiado baja, mueva el primer puntero aumentando la suma; si la suma es demasiado alta, mueva el segundo puntero disminuyéndola.
Supongamos que la suma es correcta. Esto significa que uno apunta a (a, x) y al segundo a (b, y) donde a + b = S-e. Aumente el contador en x * y y mueva ambos punteros (podría mover solo un puntero, pero en el siguiente paso no habría coincidencia, y el segundo puntero se movería en ese momento).
Por ejemplo, para [(2,4), (4,4), (6,1)] matriz y Se = 8, los puntos primero puntero en (2,4) y el segundo en (6,1) Como 2 + 6 = 8, agrega 4 y mueve ambos punteros. Ahora ambos apuntan a (4,4), por lo que aumenta el contador por 16. ¡No se detengan! Los punteros se superan, y se obtiene primero en (6,1), segundo en (2,4), aumenta el contador en 4.
Entonces, al final, hay 4 + 16 + 4 = 24 8 maneras de conseguir como una suma de 4 elementos de [1,1,3]:
>>> len([k for k in itertools.product([1,1,3],repeat=4) if sum(k) == 8])
24
Prelude Control.Monad> length [k | k <- replicateM 4 [1,1,3], sum k == 8]
24
repetir que para cada correo, obtendrá el recuento de maneras de conseguir S como una suma de 5 elementos.
Para [1,1,1,1,1] y Se = 4, la matriz de sumas sería [(2,25)], y obtendría que hay 625 formas de obtener la suma de 4.
Para cada e, este paso es lineal en tamaño de la matriz (por lo que es O (N)), por lo que el bucle de toma O (N).
En inclusión-exclusión:
Call un quíntuple (i, j, k, l, m) "adecuado" si x [i] + x [j] + x [k] + x [ l] + x [m] = S. El objetivo es contar el número de quíntuples adecuados (i, j, k, l, m) donde i, j, k, l, m son distintos por pares. El algoritmo principal puede contar en O (N^3) cuántos hay quíntuples adecuados que no tienen necesariamente componentes distintos. Lo que resta es contar esas tuplas "incorrectas".
Considere los subconjuntos de adecuada quintuplica
A xy = {(i, j, k, l, m): índices en x-ésimo y y-º lugar son los mismos}
Por ejemplo, A es el conjunto de quintuplica adecuado (i, j, k, l, m), donde j = l.
El conjunto de mal quintuplica es:
Un ∪ A ∪ ... ∪ A
Contando su cardinalidad de inclusión-exclusión:
| Un ∪ A ∪ ... ∪ A | = | A | + | A | + ... + | A | - | A ∩ A | - ... - | A ∩ A | + ... + | A ∩ A ... ∩ ∩ A ∩ A |
Hay 2 = 1024 sumideres aquí. Pero muchas de las cardinalidades son iguales.
Las únicas cosas que hay que contar es:
- X = | A | - quintuplica con i = j
- X = | A ∩ A | - quíntuples con i = j = k
- X = | A ∩ A ∩ A | - quíntuples con i = j = k = l
- X = | A ∩ A ∩ A ∩ A | - quíntuples con i = j = k = l = m
- X = | A ∩ A | - quíntuples con i = j, k = l
- X = | A ∩ A ∩ A | - quíntuples con i = j = k, l = m
Puede observar que, al permutar, todos los demás juegos se representan aquí. Por ejemplo, A tiene la misma cardinalidad que A .
Counting cardinalidades de esos 6 juegos es bastante fácil. Para el primero, crea arrays {2a + b} y {c + d} y cuenta cuántos hay elementos comunes; para los demás, solo hay 3 o menos variables libres, por lo que incluso un simple bucle le dará O (N^3).
Para simplificar la suma, escribí el siguiente programa Haskell:
import Control.Monad
import Data.List
import qualified Data.Map as Map
-- Take equivalence relation, like [(1,2),(2,3)] and return its partition, like [3,1,1]
f xs = sort $ map length $ foldr f (map return [1..5]) xs
where f (x,y) a = let [v1] = filter (x `elem`) a
[v2] = filter (y `elem`) a
in if v1 == v2 then a else (a \\ [v1,v2]) ++ [v1++v2]
-- All 1024 subsets of [(1,2),(1,3), ..., (4,5)]
subsets = filterM (const [False, True]) [(i,j) | i <- [1..5], j <- [i+1..5]]
res = Map.fromListWith (+) $ map (\k -> (f k, (-1)^(length k))) subsets
*Main> res
Loading package array-0.3.0.1 ... linking ... done.
Loading package containers-0.3.0.0 ... linking ... done.
fromList [([1,1,1,1,1],1),([1,1,1,2],-10),([1,1,3],20),([1,2,2],15),([1,4],-30),([2,3],-20),([5],24)]
lo que significa que la fórmula es
todos los subconjuntos - 10X + 20X - 30X + 24X + 15X - 20X .
Comprobar:
¿Cuántos hay en quintuplica [0,0,0, ..., 0] que suman 0?Una forma de calcular que es directamente, segunda forma es utilizar la fórmula (y no se preocupan por posiciones distintas):
direct x = x*(x-1)*(x-2)*(x-3)*(x-4)
indirect x = x^5 - 10 * x^4 + 20 * x^3 + 15 * x^3 - 30 * x^2 - 20*x^2 + 24*x
*Main> direct 100
9034502400
*Main> indirect 100
9034502400
Otras observaciones:
Además, hay O (un registro n un n) solución: Compute (x un + ... + x un n) usando FFT, el resultado es el coeficiente en x S. Esto permite una cierta i para ser utilizado dos veces, pero se puede restar polinomios como (x 2a + ... + x 2a n) * (x un + ... + x a n) etc. de acuerdo con el principio de inclusión-exclusión.
En algunos modelos de computación restringidos, ha sido shown la versión de decisión de este problema requiere O (N^3) tiempo.
sus números son positivos/negativos y 0? – tanascius
Creo que la mejor solución no puede ser menos que O (2^n), porque es la complejidad lo que necesita para obtener todos los subconjuntos posibles del conjunto dado – Andrey
Esto es más un problema matemático complejo que uno de programación, pero supongo todavía cuenta. Solo esperemos que alguien inteligente pueda resolver este problema por usted. –