Menu Close

Mes: mayo 2021

Suma de no múltiplos

El enunciado del problema 1 de la Fase Local de la Olimpiada Matemática Española del 2011 es

Dado un entero positivo n, hallar la suma de todos los enteros positivos inferiores a 10n que no son múltiplos de 2 ni de 5.

Definir la función

   suma :: Integer -> Integer

tal que (suma n) es la suma de todos los enteros positivos inferiores a 10n que no son múltiplos de 2 ni de 5. Por ejemplo,

   suma 7  ==  980
   length (show (suma (10^(10^5))))  ==  200002
   length (show (suma (10^(10^6))))  ==  2000002
   length (show (suma (10^(10^7))))  ==  20000002

Soluciones

import Data.List ((\\))
import Test.QuickCheck (Property, (==>), quickCheck)
 
-- 1ª solución
-- ===========
 
suma :: Integer -> Integer
suma n =
  sum [x | x <- [1..10*n],
           x `mod` 2 /= 0,
           x `mod` 5 /= 0]
 
-- 2ª solución
-- ===========
 
suma2 :: Integer -> Integer
suma2 n =
  sum ([1..10*n] \\ ([2,4..10*n] ++ [5,10..10*n]))
 
-- 3ª solución
-- ===========
 
-- Observando los siguientes cálculos
--    λ> map suma [1..10]
--    [20,80,180,320,500,720,980,1280,1620,2000]
--    λ> map (`div` 20) it
--    [1,4,9,16,25,36,49,64,81,100]
 
suma3 :: Integer -> Integer
suma3 n = 20*n^2
 
-- Comprobación de equivalencia
-- ============================
 
-- La propiedad es
prop_suma :: Integer -> Property
prop_suma n =
  n > 0 ==>
  all (== (suma n))
      [suma2 n,
       suma3 n]
 
-- La comprobación es
--    λ> quickCheck prop_suma
--    +++ OK, passed 100 tests.
 
-- Comparación de eficiencia
-- =========================
 
-- La comparación es
--    λ> suma (2*10^3)
--    80000000
--    (0.05 secs, 6,671,720 bytes)
--    λ> suma2 (2*10^3)
--    80000000
--    (2.63 secs, 7,886,190,192 bytes)
--    λ> suma3 (2*10^3)
--    80000000
--    (0.02 secs, 106,736 bytes)
--
--    λ> suma (4*10^5)
--    3200000000000
--    (2.31 secs, 1,314,056,144 bytes)
--    λ> suma3 (4*10^5)
--    3200000000000
--    (0.02 secs, 106,808 bytes)

Nuevas soluciones

  • En los comentarios se pueden escribir nuevas soluciones.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

Suma de serie racional

El enunciado del problema 6 de la Fase Local de la Olimpiada Matemática Española del 2020 es

Sea n un entero positivo. Calcular la siguiente suma

         3           4           5                    n+2
     --------- + --------- + --------- + ··· + ---------------------
      1·2·4·5     2·3·5·6     3·4·6·7           n·(n+1)·(n+3)·(n+4)

Definir la función

   sumaSerie :: Integer -> Rational

tal que para cada entero positivo n, (sumaSerie n) es el valor de la siguiente sumaSerie

      3           4           5                    n+2
  --------- + --------- + --------- + ··· + ---------------------
   1·2·4·5     2·3·5·6     3·4·6·7           n·(n+1)·(n+3)·(n+4)

Por ejemplo,

   sumaSerie 1        ==  3 % 40
   sumaSerie 2        ==  7 % 72
   sumaSerie 3        ==  3 % 28
   sumaSerie (10^10)  ==  3125000001562500000 % 25000000012500000001
 
   length (show (sumaSerie (10^10)))      ==  42
   length (show (sumaSerie (10^(10^2))))  ==  402
   length (show (sumaSerie (10^(10^3))))  ==  4002
   length (show (sumaSerie (10^(10^4))))  ==  40002
   length (show (sumaSerie (10^(10^5))))  ==  400002
   length (show (sumaSerie (10^(10^6))))  ==  4000002

Soluciones

import Test.QuickCheck (Property, (==>), quickCheck)
 
-- 1ª solución
-- ===========
 
sumaSerie :: Integer -> Rational
sumaSerie n =
  sum [k/((k-1)*(k-2)*(k+1)*(k+2))
      | a <- [3..n+2],
        let k = fromIntegral a]
 
-- 2ª solución
-- ===========
 
-- Calculando los primeros términos
--    λ> [sumaSerie n | n <- [1..11]]
--    [3 % 40,7 % 72,3 % 28,9 % 80,25 % 216,33 % 280,21 % 176,13 % 108,63 % 520,75 % 616,11 % 90]
-- y usando Wolfram Alpha https://bit.ly/2PvoCEK
 
sumaSerie2 :: Integer -> Rational
sumaSerie2 n = m*(m+5)/(8*(m+1)*(m+4))
  where m = fromIntegral n
 
-- Comprobación de equivalencia
-- ============================
 
-- La propiedad es
prop_sumaSerie :: Integer -> Property
prop_sumaSerie n =
  n > 0 ==>
  sumaSerie n == sumaSerie2 n
 
-- La comprobación es
--    λ> quickCheck prop_sumaSerie
--    +++ OK, passed 100 tests.
 
-- Comparación de eficiencia
-- =========================
 
-- La comparación es
--    λ> sumaSerie (10^6)
--    31250156250 % 250001250001
--    (4.99 secs, 6,029,246,016 bytes)
--    λ> sumaSerie2 (10^6)
--    31250156250 % 250001250001
--    (0.02 secs, 123,280 bytes)
  • En los comentarios se pueden escribir nuevas soluciones.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

Múltiplos persistentes de siete

El enunciado del problema 1 de la Fase Local de la Olimpiada Matemática Española del 2021 es

Determinar todos los números de cuatro cifras tales que al insertar un dígito 0 en cualquier posición se obtiene un múltiplo de 7.

Un número n se dice que es un múltiplo persistente de 7 si al insertar el dígito 0 en cualquier posición de n se obtiene un múltiplo de 7.

Definir las funciones

   esMultiploPersistente :: Integer -> Bool
   multiplosPersistentes :: Int -> [Integer]

tales que

  • (esMultiploPersistente n) se verifica si n es un múltiplo persistente de n. Por ejemplo,
     esMultiploPersistente 7007  ==  True
     esMultiploPersistente 7107  ==  False
  • (multiplosPersistentes k) es la lista de los números con k dígitos que son múltiplos persistentes de 7. Por ejemplo,
     take 2 (multiplosPersistentes 4)   ==  [7000,7007]
     length (multiplosPersistentes 20)  ==  524288

Usando la función multiplosPersistentes, calcular la respuesta al problema de la Olimpiada.

Soluciones

import Data.List (sort)
 
-- 1ª definición de esMultiploPersistente
-- ======================================
 
esMultiploPersistente :: Integer -> Bool
esMultiploPersistente n =
  and [x `mod` 7 == 0 | x <- insertados n]
 
-- (insertados n) es la lista de los números obtenidos insertando un 0
-- en cualquier posición de n. Por ejemplo,
--    insertados 3264  ==  [3264,30264,32064,32604,32640]
insertados :: Integer -> [Integer]
insertados n =
  [read (xs ++ "0" ++ ys) | k <- [0..length ns],
                            let (xs,ys) = splitAt k ns]
  where ns = show n
 
-- 1ª definición de multiplosPersistentes
-- ======================================
 
multiplosPersistentes :: Int -> [Integer]
multiplosPersistentes n =
  filter esMultiploPersistente [10^(n-1)..10^n-1]
 
-- 2ª definición de multiplosPersistentes
-- ======================================
 
multiplosPersistentes2 :: Int -> [Integer]
multiplosPersistentes2 n =
  filter esMultiploPersistente [7*10^(n-1),7*10^(n-1)+7..7*((10^n-1) `div` 9)]
 
-- 3ª definición de esMultiploPersistente
-- ======================================
 
-- Observando los cálculos
--    multiplosPersistentes2 1  ==  [7]
--    multiplosPersistentes2 2  ==  [70,77]
--    multiplosPersistentes2 3  ==  [700,707,770,777]
--    multiplosPersistentes2 4  ==  [7000,7007,7070,7077,7700,7707,7770,7777]
 
esMultiploPersistente2 :: Integer -> Bool
esMultiploPersistente2 n =
  all (`elem` "07") (show n)
 
-- 3ª definición de multiplosPersistentes
-- ======================================
 
multiplosPersistentes3 :: Int -> [Integer]
multiplosPersistentes3 n =
  filter esMultiploPersistente2 [7*10^(n-1),7*10^(n-1)+7..7*((10^n-1) `div` 9)]
 
-- 4ª definición de multiplosPersistentes
-- ======================================
 
multiplosPersistentes4 :: Int -> [Integer]
multiplosPersistentes4 k =
  sort [read (reverse cs) | cs <- aux k]
  where aux 1 = ["7"]
        aux n = map ('0':) xs ++ map ('7':) xs
          where xs = aux (n-1)
 
-- Comprobación de equivalencia
-- ============================
 
-- La propiedad es
prop_multiplosPresistentes :: Int -> Bool
prop_multiplosPresistentes n =
  all (== (multiplosPersistentes n))
      [multiplosPersistentes2 n,
       multiplosPersistentes3 n,
       multiplosPersistentes4 n]
 
-- La comprobación es
--    λ> all prop_multiplosPresistentes [1..6]
--    True
 
-- Comparación de eficiencia
-- =========================
 
-- La comparación es
--    λ> length (multiplosPersistentes 6)
--    32
--    (3.35 secs, 7,378,373,000 bytes)
--    λ> length (multiplosPersistentes2 6)
--    32
--    (0.12 secs, 171,735,992 bytes)
--    λ> length (multiplosPersistentes3 6)
--    32
--    (0.03 secs, 9,290,744 bytes)
--    λ> length (multiplosPersistentes4 6)
--    32
--    (0.01 secs, 294,584 bytes)
--
--    λ> length (multiplosPersistentes2 8)
--    128
--    (7.76 secs, 18,659,185,520 bytes)
--    λ> length (multiplosPersistentes3 8)
--    128
--    (0.73 secs, 1,007,383,168 bytes)
--    λ> length (multiplosPersistentes4 8)
--    128
--    (0.01 secs, 960,808 bytes)
--
--    λ> length (multiplosPersistentes3 9)
--    256
--    (6.82 secs, 10,517,232,576 bytes)
--    λ> length (multiplosPersistentes4 9)
--    256
--    (0.01 secs, 1,912,136 bytes)

Nuevas soluciones

  • En los comentarios se pueden escribir nuevas soluciones.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

Múltiplos repitunos (OME1993 P4)

El enunciado del problema 4 de la OME (Olimpiada Matemática Española) del 1993 es

Demostrar que para todo número primo p distinto de 2 y de 5, existen infinitos múltiplos de p de la forma 1111……1 (escrito sólo con unos).

Definir la función

   multiplosRepitunos :: Integer -> [Integer]

tal que (multiplosRepitunos p n) es la lista de los múltiplos repitunos de p (es decir, de la forma 1111…1 escrito sólo con unos), donde p es un número primo distinto de 2 y 5. Por ejemplo,

   take 2 (multiplosRepitunos 7) == [111111,111111111111]
   head (multiplosRepitunos 19)  == 111111111111111111
   length (show (head (multiplosRepitunos (primes !! (10^5))))) == 43324

Comprobar con QuickCheck que para todo primo p mayor que 5 y todo número entero positivo n, existe un mútiplo repituno de p mayor que n.

Soluciones

import Data.Numbers.Primes (primes)
import Test.QuickCheck (Property, (==>), quickCheck)
 
-- 1ª solución
-- ===========
 
multiplosRepitunos :: Integer -> [Integer]
multiplosRepitunos p =
  [x | x <- repitunos
     , mod x p == 0]
 
-- repitunos es la lista de los números de la forma 111...1 (escrito sólo con
-- unos). Por ejemplo,
--    take 5 repitunos  ==  [1,11,111,1111,11111]
repitunos :: [Integer]
repitunos = 1 : [10*x+1 | x <- repitunos]
 
-- 2ª solución
-- ===========
 
multiplosRepitunos2 :: Integer -> [Integer]
multiplosRepitunos2 p =
  [x | x <- repitunos2
     , mod x p == 0]
 
repitunos2 :: [Integer]
repitunos2 = [div (10^n-1) 9 | n <- [1..]]
 
-- Comparación de eficiencia
-- =========================
 
-- La comparación es
--    λ> length (show (head (multiplosRepitunos (primes !! (10^5)))))
--    43324
--    (0.58 secs, 1,272,561,448 bytes)
--    λ> length (show (head (multiplosRepitunos2 (primes !! (10^5)))))
--    43324
--    (5.50 secs, 2,563,458,656 bytes)
 
-- Comprobación
-- ============
 
-- La propiedad es
prop_multiplosRepitunos :: Int -> Property
prop_multiplosRepitunos k =
  k > 2  ==>
  not (null (multiplosRepitunos (primes !! k)))
 
-- La comprobación es
--    λ> quickCheck prop_multiplosRepitunos
--    +++ OK, passed 100 tests.

Nuevas soluciones

  • En los comentarios se pueden escribir nuevas soluciones.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>

Ecuación diofántica con primos (OME1995 P4)

El enunciado del problema 4 de la OME (Olimpiada Matemática Española) del 1995 es

Siendo p un número primo, halla las soluciones enteras de la ecuación:

p.(x + y) = x.y

Definir la función

   soluciones :: Integer -> [(Integer, Integer)]

tal que (soluciones p) es la lista de los pares de enteros (x,y) tales que p.(x + y) = x.y. Por ejemplo,

   λ> take 3 (soluciones 7)
   [(0,0),(14,14),(-42,6)]
   λ> sum [x+y | (x,y) <- take 6 (soluciones (primes !! (10^6)))]
   185830404

Soluciones

import Data.List (sort)
import Data.Numbers.Primes (primes)
 
-- 1ª solución
-- ===========
 
soluciones :: Integer -> [(Integer, Integer)]
soluciones p =
  [(x,y) | (x,y) <- pares,
           p * (x + y) == x * y]
 
-- pares es la lista de los pares de números enteros ordenados por la
-- suma de los valores absolutos de sus componentes. Por ejemplo,
--    λ> take 38 pares
--    [(0,0),(-1,0),(0,-1),(0,1),(1,0),(-2,0),(-1,-1),(-1,1),(0,-2),
--     (0,2),(1,-1),(1,1),(2,0),(-3,0),(-2,-1),(-2,1),(-1,-2),(-1,2),
--     (0,-3),(0,3),(1,-2),(1,2),(2,-1),(2,1),(3,0),(-4,0),(-3,-1),
--     (-3,1),(-2,-2),(-2,2),(-1,-3),(-1,3),(0,-4),(0,4),(1,-3),(1,3),
--     (2,-2),(2,2)]
pares :: [(Integer,Integer)]
pares = concatMap paresEnterosSuma [0..]
 
-- (paresEnterosSuma n) es la lista de pares de enteros (x,y) tales que la suma
-- de los valores absolutos de x e y es igual a n. Por ejemplo,
--    λ> paresEnterosSuma 3
--    [(-3,0),(-2,-1),(-2,1),(-1,-2),(-1,2),(0,-3),(0,3),(1,-2),(1,2),
--     (2,-1),(2,1),(3,0)]
paresEnterosSuma :: Integer -> [(Integer,Integer)]
paresEnterosSuma n = concatMap aux [-n..n]
  where aux k | m == 0    = [(k,0)]
              | otherwise = [(k,-m),(k,m)]
          where m = n - abs k
 
-- 2ª solución
-- ===========
 
-- Observando los siguientes cálculos:
--    take 6 (soluciones 2)  == [(0,0),(-2,1),(1,-2),(4,4),(3,6),(6,3)]
--    take 6 (soluciones 3)  == [(0,0),(-6,2),(2,-6),(6,6),(4,12),(12,4)]
--    take 6 (soluciones 5)  == [(0,0),(10,10),(-20,4),(4,-20),(6,30),(30,6)]
--    take 6 (soluciones 7)  == [(0,0),(14,14),(-42,6),(6,-42),(8,56),(56,8)]
--    take 6 (soluciones 11) == [(0,0),(22,22),(-110,10),(10,-110),(12,132),(132,12)]
 
soluciones2 :: Integer -> [(Integer, Integer)]
soluciones2 2 = [(0,0),(-2,1),(1,-2),(4,4),(3,6),(6,3)]
soluciones2 3 = [(0,0),(-6,2),(2,-6),(6,6),(4,12),(12,4)]
soluciones2 p =
  [(0,0), (2*p,2*p), (p*(1-p),p-1), (p-1,p*(1-p)), (p+1,p*(p+1)), (p*(p+1),p+1)]
 
-- Comparación de equivalencia
-- ===========================
 
-- La propiedad es
prop_equivalencia :: Bool
prop_equivalencia =
  and [ take 6 (soluciones p) == soluciones2 p
      | p <- takeWhile (<= 37) primes]
 
-- La comprobación es
--    λ> prop_equivalencia
--    True
 
-- Comparación de eficiencia
-- =========================
 
-- La comparación es
--    λ> take 6 (soluciones 37)
--    [(0,0),(74,74),(-1332,36),(36,-1332),(38,1406),(1406,38)]
--    (3.88 secs, 2,521,196,352 bytes)
--    λ> take 6 (soluciones2 37)
--    [(0,0),(74,74),(-1332,36),(36,-1332),(38,1406),(1406,38)]
--    (0.01 secs, 144,192 bytes)

Nuevas soluciones

  • En los comentarios se pueden escribir nuevas soluciones.
  • El código se debe escribir entre una línea con <pre lang="haskell"> y otra con </pre>