嘘~ 正在从服务器偷取页面 . . .

洛谷P1727 计算π 题解


洛谷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 方法


参考文献

[1] https://www.luogu.com.cn/article/42mm7y25

[2] 梅钦类公式 - 维基百科,自由的百科全书


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录