UVALive8201BBP Formula

8201-BBP Formula

Time limit: 3.000 seconds

In 1995, Simon Plouffe discovered a special summation style for some constants. Two year later, together with the paper of Bailey and Borwien published, this summation style was named as the Bailey-Borwein-Plouffe formula.Meanwhile a sensational formula appeared. That is

π = ∑k=0∞ 16-k (4/(8*k + 1) − 2/(8*k + 4) − 1/(8*k + 5) − 1/(8*k + 6))

  For centuries it had been assumed that there was no way to compute the n-th digit of π without calculating allof the preceding n − 1 digits, but the discovery of this formula laid out the possibility. This problem asks you to calculate the hexadecimal digit n of π immediately after the hexadecimal point. For example, the hexadecimalformat of n is 3.243F6A8885A308D313198A2E... and the 1-st digit is 2, the 11-th one is A and the 15-th one is D.

Input

The first line of input contains an integer T (1 ≤ T ≤ 32) which is the total number of test cases. Each of the following lines contains an integer n (1 ≤ n ≤ 100000).

Output

For each test case, output a single line beginning with the sign of the test case. Then output the integer n, and the answer which should be a character in {0, 1, ... , 9, A, B, C, D, E, F} as a hexadecimal number 

Sample Input

5

1

11

111

1111

11111

Sample Output

Case #1: 1 2

Case #2: 11 A

Case #3: 111 D

Case #4: 1111 A

Case #5: 11111 E

 

题解

  对于一个十进制小数x,要想获取其第n位的十六进制小数,只需先将x转为十六进制后再将小数点右移n位,则小数点左边第一个整数位对应的数字即为答案。但由于n很大,直接计算显然不行,精度不够,那该怎么办呢?事实上,如果要我们求x的第n位十进制小数,我们直接将x乘以10,即将x小数点右移了n位。对于十六进制,同理,只需将x乘以16,即将十六进制下x的小数点右移了n位。主要思想有了,我们就可以解这道题了。

  对于公式π = ∑k=0∞ 16-k (4/(8*k + 1) − 2/(8*k + 4) − 1/(8*k + 5) − 1/(8*k + 6)),我们可以转化为π = 4∑1 - 2∑2 - ∑3 - ∑4,其中

∑1 =  ∑k=0 16-k/(8*k + 1)

∑2 =  ∑k=0∞ 16-k/(8*k + 4)

∑3 =  ∑k=0∞ 16-k/(8*k + 5)

∑4 =  ∑k=0∞ 16-k/(8*k + 6)

 

我们取∑1分析,其他三个同理。对于∑1,由于我们要求的是第n位小数数字,故我们先将小数点右移n-1位,即

∑1 = k=0n-1 16n-1-k/(8*k + 1)  + k=n 16n-1-k/(8*k + 1)

由前面分析知,整数部分对最终答案没有影响,故可以通过取模去除整数部分,保留小数部分。

∑1 = ∑k=0n-1 [16n-1-k mod (8*k + 1)] / (8*k + 1)   + ∑k=n 16n-1-k/(8*k + 1)

 ∑1的前半部分通过快速幂很容易实现;而由级数的知识可以知道,∑1的后半部分会收敛到一个常数,即随着k的增大,对应的项则越来越趋于0。故∞可以取为一个稍大的数,比如500之类的。

 1 #include <bits/stdc++.h>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <algorithm>
 6 #define re register
 7 #define il inline
 8 #define ll long long
 9 #define ld long double
10 using namespace std;
11 const ll MAXN = 1e2+5;
12 const ll TABLE = 26;
13 const ld INF = 1e9;
14 const ld EPS = 1e-9;
15 
16 //快速幂模
17 ll powmod(ll a, ll n, ll md)
18 {
19     ll ans = 1;
20     while(n)
21     {
22         if(n&1)
23         {
24             ans = (ans*a)%md;
25         }
26         a = (a*a)%md;
27         n >>= 1;
28     }
29     return ans;
30 }
31 
32 //BBP Formula
33 ll BBP(ll n)
34 {
35     ld ans = 0;
36     ld ans1 = 0, ans2 = 0, ans3 = 0, ans4 = 0;
37     for(re ll i = 0; i < n; ++i)
38     {
39         ll k = n-1-i;
40         ll a = 8*i+1;
41         ll b = a + 3;
42         ll c = a + 4;
43         ll d = a + 5;
44         /*
45         //最好用这种(先算总和,最后作加减,以免产生截断误差。
46         ans1 += powmod(16,k,a)/(ld)a;
47         ans2 += powmod(16,k,b)/(ld)b;
48         ans3 += powmod(16,k,c)/(ld)c;
49         ans4 += powmod(16,k,d)/(ld)d;
50         */
51         ans += 4*powmod(16,k,a)/(ld)a-2*powmod(16,k,b)/(ld)b-powmod(16,k,c)/(ld)c-powmod(16,k,d)/(ld)d;
52     }
53     for(re ll i = n; i <= n+10; ++i)
54     {
55         ll k = n-1-i;
56         ll a = 8*i+1;
57         ll b = a + 3;
58         ll c = a + 4;
59         ll d = a + 5;
60         /*
61         //最好用这种(先算总和,最后作加减,以免产生截断误差。
62         ans1 += powl(16,k)/a;
63         ans2 += powl(16,k)/b;
64         ans3 += powl(16,k)/c;
65         ans4 += powl(16,k)/d;
66         */
67         ans += 4.0*powl(16.0,(ld)k)/a-2.0*powl(16.0,(ld)k)/b-1.0*powl(16.0,(ld)k)/c-1.0*powl(16.0,(ld)k)/d;
68     }
69     //最好用这种(先算总和,最后作加减,以免产生截断误差。
70     //ld ans = 4*ans1 - (2*ans2 + ans3 + ans4);
71     ans -= (ll)ans;
72     ans = ans < 0 ? ans+1 : ans;
73     return ((ll)(ans*16))%16;
74 }
75 
76 //这题推荐用scanf和printf
77 //cin和cout出现玄学错误
78 //具体原因等找到再作说明
79 int main()
80 {
81     ios::sync_with_stdio(false);
82     int T;
83     //scanf("%d", T);
84     cin >> T;
85     for(re int i = 1; i <= T; ++i)
86     {
87         int n;
88         //scanf("%d", &n);
89         cin >> n;
90         ll ans = BBP(n);
91         cout << "Case #" << dec << i << ": " << dec << n << " ";
92         cout << setiosflags(ios::uppercase) << hex << ans << endl;
93         //printf("Case #%d: %d %c\n", i, n, out(ans));
94     }
95     return 0;
96 }
View Code
原文地址:https://www.cnblogs.com/BlueHeart0621/p/11812773.html