大致题意是计算Π的小数点后第n位的值。
这道题最主要的地方是bbp公式
圆周率每乘以一个16,就相当于把十六进制的圆周率小数点向右移动一位,移动b位就是乘以16^b,而BBP公式给出的级数,可以分解成两项关于b的函数,f1(b)给出的就是圆周率移动b位的整数部分数值,f2(b) 给出的是圆周率移动b位的小数数值,所以利用f2(b)就可以计算圆周率b项之后的数字,而不需要知道第一项f1(b)的值。
抽取第一部分
拆分
拆分之后我们就可以得到第 n 位。将式子乘上 16^n ,使得小数点往后移动 n 位。
前一项为了避免高精度可化成后一项只需将取合适值。
令所以结果为的小数部分。
因为得到的只是小数部分,所以再乘以 16后,得到的整数部分转化成十六进制就可以啦。
代码:
#include<iostream>
#include<math.h>
typedef long long LL;
using namespace std;
char out(int x) {
if(0 <= x && x <= 9) return x + '0';
else if(x == 10) return 'A';
else if(x == 11) return 'B';
else if(x == 12) return 'C';
else if(x == 13) return 'D';
else if(x == 14) return 'E';
else if(x == 15) return 'F';
}
LL qpower(LL a, LL b, LL mod)
{
LL res = 1;
while(b)
{
if(b & 1) res = a * res % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
double bbp(int n,LL k,LL b)
{
double val=0;int i;
for(i=0;i<n+1;i++)
{
val+=(qpower(16,n-i,8*i+b) * 1.0/(8*i+b));
}
for(i=n+1;i<n+1000+1;i++) //此处无穷大取多1000
{
val+=powf(16,n-i)/(8*i+b);
}
return k*val;
}
int main()
{
int t,n;
cin>>t;
int cas = 1;
while(t--)
{
double ans = 0;
cin>>n;
n--;
ans = bbp(n,4,1) - bbp(n,2,4) - bbp(n,1,5) - bbp(n,1,6);
ans = ans - (int)ans;
if(ans<0)ans+=1;
ans*=16;
char c;
c=out((int)ans);
printf("Case #%d: %d %c\n",cas++,n+1,c);
}
return 0;
}