Python - 191 байт
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]))
~ В 4 раза быстрее версия - 206 байт
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]))
Ввод взят из стандартного ввода. Вывод для n = 5000 занимает примерно 14 секунд со вторым сценарием (или 60 секунд с первым).
Пример использования:
$ 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 n - это n- й переменный номер , который можно формально определить как число чередующихся перестановок в наборе размера n (см. также: A000111 ). Альтернативно, последовательность может быть определена как композиция чисел касательных и секущих чисел ( A 2n = S n , A 2n + 1 = T n ), подробнее об этом позже.
Малый поправочный коэффициент c n быстро сходится к 1, когда n становится большим, и определяется как:
Для n = 1 это равносильно оценке ряда Лейбница . Приближая π к 10 ½ , количество необходимых терминов можно рассчитать как:
который сходится (округляется) до 17 , хотя меньшие значения n требуют значительно большего.
Для вычисления A n существует несколько алгоритмов и даже явная формула, но все они квадратичны по n . Первоначально я кодировал реализацию алгоритма Зайделя , но он оказывается слишком медленным, чтобы быть практичным. Каждая итерация требует сохранения дополнительного слагаемого, и слагаемые увеличиваются по величине очень быстро («неправильный» тип O (n 2 ) ).
Первый сценарий использует реализацию алгоритма, первоначально заданного Кнутом и Бакгольцем :
Пусть T 1, k = 1 для всех k = 1..n
Последующие значения T задаются рекуррентным соотношением:
T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]
Тогда A n определяется как T n, 1
(см. также: A185414 )
Хотя это и не указано явно, этот алгоритм рассчитывает и Касательные Числа и Числа Секанта одновременно. Второй сценарий использует вариант этого алгоритма Брента и Циммермана , который вычисляет либо T, либо S , в зависимости от четности n . Улучшение является квадратичным по n / 2 , следовательно, улучшение в ~ 4 раза.