Python - 191 bytes
t=i=1L;k=n=input();f=2000*20**n;A=range(n+1)
for k in range(2,n):A=[(A[j-1]+A[j+1])*j>>1for j in range(n-k+1)];f*=k
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))
~ Versión 4 veces más rápida: 206 bytes
t=i=1L;k=n=input();f=2000*20**n;A=[0,1]+[0]*n
for k in range(1,n):
f*=k
for j in range(-~n/2-k+1):A[j]=j*A[j-1]+A[j+1]*(j+2-n%2)
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))
La entrada se toma de stdin. La salida para n = 5000 tarda aproximadamente 14 segundos con el segundo script (o 60 segundos con el primero).
Uso de la muestra:
$ echo 1 | python pi-trunc.py
1
$ echo 2 | python pi-trunc.py
14
$ echo 3 | python pi-trunc.py
6
$ echo 4 | python pi-trunc.py
13
$ echo 5 | python pi-trunc.py
24
$ echo 50 | python pi-trunc.py
211
$ echo 500 | python pi-trunc.py
2305
$ echo 5000 | python pi-trunc.py
22852
La fórmula utilizada es la siguiente:
donde A n es el enésimo número alterno , que se puede definir formalmente como el número de permutaciones alternas en un conjunto de tamaño n (ver también: A000111 ). Alternativamente, la secuencia se puede definir como la composición de los números de tangente y los números de la secuencia ( A 2n = S n , A 2n + 1 = T n ), más sobre eso más adelante.
El pequeño factor de corrección c n converge rápidamente a 1 cuando n se hace grande y viene dado por:
Para n = 1 , esto equivale a evaluar la Serie Leibniz . Aproximando π como 10 ½ , el número de términos requeridos puede calcularse como:
que converge (redondeado) a 17 , aunque los valores más pequeños de n requieren considerablemente más.
Para el cálculo de A n hay varios algoritmos, e incluso una fórmula explícita, pero todos ellos son cuadrática por n . Originalmente codifiqué una implementación del algoritmo de Seidel , pero resulta demasiado lento para ser práctico. Cada iteración requiere que se almacene un término adicional, y los términos aumentan en magnitud muy rápidamente (el tipo "incorrecto" de O (n 2 ) ).
El primer script usa una implementación de un algoritmo originalmente proporcionado por Knuth y Buckholtz :
Sea T 1, k = 1 para todo k = 1..n
Los valores posteriores de T están dados por la relación de recurrencia:
T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]
Entonces A n viene dada por T n, 1
(ver también: A185414 )
Aunque no se indica explícitamente, este algoritmo calcula tanto los números de tangente como los números de secuencia simultáneamente. El segundo script utiliza una variación de este algoritmo de Brent y Zimmermann , que calcula T o S , dependiendo de la paridad de n . La mejora es cuadrática por n / 2 , de ahí la mejora de velocidad ~ 4x.