洛谷P1727 计算π 题解
题目链接:P1727 计算π
题意:
计算 $\pi$ 的小数点后 $n(n \le 10000)$ 位。
输入格式:
一行,$n$
输出格式:
先输出一行
3.
,然后$10$ 个数一空格,$50$ 个数一换行。
学 OI 这么久,我居然不会计算圆周率。
首先有梅钦公式
接着有麦克劳林级数
然后用 Python 打个表,C++ 输出即可。
时间复杂度 $\mathcal{O}(n^2)$
Python 代码:
n = int(input())
_1 = 10 ** (n + 10)
a = _1 * 4 // 5
b = _1 // -239
sum = a + b
for i in range(3, n * 2, 2):
a //= -25
b //= -57121
sum += (a + b) // i
pi = sum * 4
pi = pi // 10 ** 10 - 3 * 10 ** n
# print("3.%s" % (pi))
print("3%s" % (pi), file = open('check.out', 'w'))
C++ 代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define N ((int)())
#define S(x) #x
char s[] = S(3141592...); // 这个表太长了我不贴全了
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
int n; cin >> n; cout << "3.\n";
for(int i = 1; i <= n; i++) {
cout << s[i];
if(i % 10 == 0) cout << " \n"[i % 50 == 0];
}
return 0;
}
不过听说直接用梅钦公式收敛速度可能慢一些
那就顺便科普一下梅钦类公式吧,听说收敛更快,但复杂度其实没变。
梅钦类公式(Machin-like formula)
其中 $a_n,b_n$ 为正整数且 $a_n < b_n$ ,$c_n$ 为非零整数,且 $c_0$ 为正整数。
什么?你问我 $a,b,c$ 是啥?其实“随便”啥都可以哦 qwq
具体地,根据角的和差公式
若 $\displaystyle -\frac{\pi}{2}<\arctan \frac{a_1}{b_1}+\arctan \frac{a_2}{b_2}<\frac{\pi}{2}$ ,则有
反复应用这个方程,就可以得到所有的梅钦类公式啦~
比如最原始的梅钦公式可以这么推导
那就给一个网上找的公式吧
如果你觉得 $\mathcal{O}(n^2)$ 太慢,可以看看参考文献1,里面有讲 $\mathcal{O}(n\log^2 n)$ 的方法
据《理性愉悦——高精度数值计算》说是目前计算初等函数时间复杂度最低的方法:AGM 方法
参考文献: