Menu Close

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>

2 soluciones de “Suma de serie racional

  1. Rubén Muñoz Mkrtchian
    import Data.Ratio
     
    -- 1ª Definición:
    -- =============
     
    sumaSerie :: Integer -> Rational
    sumaSerie n = genericIndex serieSumasParciales (n-1)
      where serieSumasParciales = scanl1 (+) terminos
            terminos = [(x+2) % (x*(x+1)*(x+3)*(x+4)) | x <- [1..]]
     
    -- 2ª Definición:
    -- =============
    --
    -- Sea (an) la sucesión cuyo enésimo término es el enésimo sumando de la serie
    -- del enunciado. La forma de los denominadores nos sugiere que podríamos estar
    -- ante una serie telescópica. Veamos que en efecto es así.
    --
    --       1            1              2n + 4
    --    -------- - ------------ = ------------------ = 2 * an
    --     n(n+3)     (n+1)(n+4)     n(n+1)(n+3)(n+4)
    --
    --             1
    --    bn = --------- ==> an = bn - b(n+1)
    --          2n(n+3)
    --
    -- Así pues, teniendo en cuenta la sucesión (bn) encontrada, sumaSerie n tendrá
    -- un valor igual a b(1) - b(n).
     
    sumaSerie2 :: Integer -> Rational
    sumaSerie2 n = a - b
      where a = 1 % 8
            b = 1 % (2*(n+1)*(n+4))
     
    -- Equivalencia de las definiciones:
    -- ================================
     
    prop :: Integer -> Bool
    prop n = sumaSerie m == sumaSerie m
      where m = abs n + 1
     
    -- La comprobación es:
    -- λ> quickCheck prop
    -- +++ OK, passed 100 tests.
    --
    -- Comparación de eficiencia:
    -- =========================
    --
    -- λ> sumaSerie 100000
    -- 312515625 % 2500125001
    -- (0.44 secs, 278,051,144 bytes)
    -- λ> sumaSerie2 100000
    -- 312515625 % 2500125001
    -- (0.01 secs, 72,712 bytes)
    --
    -- λ> length (show (sumaSerie2 (10^(10^5))))
    -- 400002
    -- (1.07 secs, 19,335,424 bytes)
  2. Alejandro García Alcaide
    import Test.QuickCheck
    -- Hacemos una primera definición de la función que buscamos. 
    sumaSerie :: Integer -> Rational
    sumaSerie n = sum [fromIntegral (t+2)/s | (t,s) <- zip [1..n] (lista n)]
     
    lista :: Integer -> [Rational]
    lista x = [fromInteger $ product [n,n+1,n+3,n+4] | n <- [1..x]]
     
    -- Esta definición es, sin embargo, ineficiente- pues no llega a calcular los
    -- casos grandes propuestos.
    -- Descomponemos en fracciones simples la sucesión:
    --
    --          n+2                  1/6            1/6         1/6         1/6
    --  ---------------------- == ---------  -   --------- - --------- +  --------
    --    n*(n+1)*(n+3)*(n+4)         n            n+1         n+3          n+4
     
    -- De aquí, podemos sacar otra definición de la función. 
    sumaSerie' :: Integer -> Rational
    sumaSerie' n = 1/6*sumaAlterna[1/fromIntegral(s+r) | s <- [1..n], r <- [0,1,3,4]]
     where sumaAlterna []           = 0
           sumaAlterna [x,y,z,f]    = x - y - z + f
           sumaAlterna (x:y:z:f:xs) = x - y - z + f + sumaAlterna xs
     
    -- Se comprueba fácilmente que es una serie análoga a la anterior.
    prop :: Integer -> Bool
    prop n = sumaSerie n == sumaSerie' n
    -- La propiedad se verifica:
    -- +++ OK, passed 100 tests.
     
     
    --Pero, si nos  damos cuenta, se trata de una serie telescópica. Luego podemos
    -- escribirla de la siguiente forma:
    --
    --                 1/6              1/6                  1/6           1/6 
    --      S_n  == (--------- - --------------------) + (----------- - ----------)
    --                  1               n+1                   4             n+4 
    -- Entonces:
     
    sumaSerieFinal :: Integer -> Rational
    sumaSerieFinal n = 1/6 - 1/(6*den1) - 1/24 + 1/(6*den2)
     where den1 = fromIntegral(n+1)
           den2 = fromIntegral(n+4)

Leave a Reply

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.