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]))
~ Versão 4x mais 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]))
A entrada é retirada do stdin. A saída para n = 5000 leva aproximadamente 14s com o segundo script (ou 60s com o primeiro).
Uso da amostra:
$ 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
A fórmula usada é a seguinte:
onde A n é o n th alternada número , que pode ser formalmente definida como o número de permutações alternada com um conjunto de tamanho N (ver também: A000111 ). Alternativamente, a sequência pode ser definida como a composição dos Números Tangentes e Secantes ( A 2n = S n , A 2n + 1 = T n ), mais sobre isso mais tarde.
O pequeno fator de correção c n converge rapidamente para 1 quando n se torna grande e é dado por:
Para n = 1 , isso equivale a avaliar a série Leibniz . Aproximando π como 10 ½ , o número de termos necessários pode ser calculado como:
que converge (arredondado) para 17 , embora valores menores de n exijam consideravelmente mais.
Para o cálculo de A n existem vários algoritmos e até uma fórmula explícita, mas todos eles são quadráticos por n . Eu originalmente codifiquei uma implementação do Algoritmo de Seidel , mas ela se torna muito lenta para ser prática. Cada iteração requer que um termo adicional seja armazenado, e os termos aumentam em magnitude muito rapidamente (o tipo "errado" de O (n 2 ) ).
O primeiro script usa uma implementação de um algoritmo originalmente dado por Knuth e Buckholtz :
Seja T 1, k = 1 para todos k = 1..n
Os valores subsequentes de T são dados pela relação de recorrência:
T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]
Um n é então dado por T n, 1
(veja também: A185414 )
Embora não esteja explicitamente declarado, esse algoritmo calcula os números tangentes e secantes simultaneamente. O segundo script usa uma variação desse algoritmo de Brent e Zimmermann , que calcula T ou S , dependendo da paridade de n . A melhoria é quadrática em n / 2 , daí a melhoria da velocidade em ~ 4x.