Suma de las sumas de los cuadrados de los divisores
La suma de las sumas de los cuadrados de los divisores de los 6 primeros números enteros positivos es
1 2 3 |
1² + (1²+2²) + (1²+3²) + (1²+2²+4²) + (1²+5²) + (1²+2²+3²+6²) = 1 + 5 + 10 + 21 + 26 + 50 = 113 |
Definir la función
1 |
sumaSumasCuadradosDivisores :: Integer -> Integer |
tal que (sumaSumasCuadradosDivisores n) es la suma de las sumas de los cuadrados de los divisores de los n primeros números enteros positivos. Por ejemplo,
1 2 |
sumaSumasCuadradosDivisores 6 == 113 sumaSumasCuadradosDivisores (10^6) == 400686363385965077 |
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
import Data.List (genericIndex) -- 1ª solución -- =========== sumaSumasCuadradosDivisores :: Integer -> Integer sumaSumasCuadradosDivisores n = sum [sumaCuadradosDivisores k | k <- [1..n]] -- (sumaCuadradosDivisores n) es la suma de los cuadrados de los -- divisores de n. Por ejemplo, -- sumaCuadradosDivisores 6 == 50 sumaCuadradosDivisores :: Integer -> Integer sumaCuadradosDivisores n = sum (map (^2) (divisores n)) -- (divisores n) es la lista de los divisores de n. Por ejemplo, -- divisores 6 == [1,6,2,3] divisores :: Integer -> [Integer] divisores 1 = [1] divisores n = 1 : n : [x | x <- [2..n `div` 2], n `mod` x == 0] -- 2ª solución -- =========== sumaSumasCuadradosDivisores2 :: Integer -> Integer sumaSumasCuadradosDivisores2 n = sumasSumasCuadradosDivisores `genericIndex` (n-1) -- sumasSumasCuadradosDivisores es la sucesión cuyo n-ésimo término es -- la suma de las sumas de los cuadrados de los divisores de n. Por -- ejemplo, -- take 6 sumasSumasCuadradosDivisores == [1,6,16,37,63,113] sumasSumasCuadradosDivisores :: [Integer] sumasSumasCuadradosDivisores = 1 : sig 1 2 where sig m n = y : sig y (n+1) where y = m + sumaCuadradosDivisores n -- 3ª solución -- =========== sumaSumasCuadradosDivisores3 :: Integer -> Integer sumaSumasCuadradosDivisores3 n = last (sumasSumasCuadradosDivisores3 n) -- (sumasSumasCuadradosDivisores3 n) es la sucesión cuyo k-ésimo término -- es la suma de las sumas de los cuadrados de los divisores de k, para -- k entre 0 y n. Por ejemplo, -- sumasSumasCuadradosDivisores3 6 == [0,6,18,36,52,77,113] sumasSumasCuadradosDivisores3 :: Integer -> [Integer] sumasSumasCuadradosDivisores3 n = scanl f 0 [1..n] where f x k = x + k^2 * (n `div` k) -- 4ª solución -- =========== sumaSumasCuadradosDivisores4 :: Integer -> Integer sumaSumasCuadradosDivisores4 n = last (sumasSumasCuadradosDivisores4 n) -- (sumasSumasCuadradosDivisores4 n) es la sucesión cuyo k-ésimo término -- es la suma de las sumas de los cuadrados de los divisores de k, para -- k entre 0 y n. Por ejemplo, -- sumasSumasCuadradosDivisores4 6 == [0,6,18,36,52,77,113] sumasSumasCuadradosDivisores4 :: Integer -> [Integer] sumasSumasCuadradosDivisores4 n = scanl1 f [0,1..n] where f x k = x + k^2 * (n `div` k) -- 5ª solución -- =========== sumaSumasCuadradosDivisores5 :: Integer -> Integer sumaSumasCuadradosDivisores5 n = last (sumasSumasCuadradosDivisores5 n) -- (sumasSumasCuadradosDivisores5 n) es la sucesión cuyo k-ésimo término -- es la suma de las sumas de los cuadrados de los divisores de k, para -- k entre 0 y n. Por ejemplo, -- sumasSumasCuadradosDivisores5 6 == [0,6,18,36,52,77,113] sumasSumasCuadradosDivisores5 :: Integer -> [Integer] sumasSumasCuadradosDivisores5 n = scanl1 f [0,1..n] where f x k = x + k * (n - (n `mod` k)) -- 6ª solución -- =========== -- Cada elemento k de [1..n], al cuadrado, aparece tantas veces como la -- parte entera de n/k; luego, -- sumaSumasCuadradosDivisores n = -- 1^2*n + 2^2*(n `div` 2) + 3^2*(n `div` 3) + ... + n^2*1 sumaSumasCuadradosDivisores6 :: Integer -> Integer sumaSumasCuadradosDivisores6 n = sum (zipWith (*) ds vs) where ds = map (^2) [1..n] vs = [n `div` k | k <- [1..n]] -- Comparación de eficiencia: -- ========================= -- λ> sumaSumasCuadradosDivisores (3*10^3) -- 10825397502 -- (3.29 secs, 468,721,192 bytes) -- λ> sumaSumasCuadradosDivisores2 (3*10^3) -- 10825397502 -- (3.25 secs, 469,462,600 bytes) -- λ> sumaSumasCuadradosDivisores3 (3*10^3) -- 10825397502 -- (0.03 secs, 2,788,752 bytes) -- λ> sumaSumasCuadradosDivisores4 (3*10^3) -- 10825397502 -- (0.03 secs, 2,813,304 bytes) -- λ> sumaSumasCuadradosDivisores5 (3*10^3) -- 10825397502 -- (0.03 secs, 1,467,056 bytes) -- λ> sumaSumasCuadradosDivisores6 (3*10^3) -- 10825397502 -- (0.03 secs, 3,291,664 bytes) -- -- λ> sumaSumasCuadradosDivisores3 (5*10^5) -- 50085873311988831 -- (2.34 secs, 440,961,640 bytes) -- λ> sumaSumasCuadradosDivisores4 (5*10^5) -- 50085873311988831 -- (2.29 secs, 444,962,904 bytes) -- λ> sumaSumasCuadradosDivisores5 (5*10^5) -- 50085873311988831 -- (1.23 secs, 220,960,152 bytes) -- λ> sumaSumasCuadradosDivisores6 (5*10^5) -- 50085873311988831 -- (2.76 secs, 524,962,464 bytes) |
En Maxima: