洛谷P1727 计算π

传送门

题目背景

《爱与愁的故事第二弹·compute》第一章。

题目描述

中秋至,博饼声铿锵不断。爱与愁大神兴致勃勃地到学校博饼,结果抱回家的只有一秀二举。爱与愁大神十分生气,打电话给月落乌啼:“喂,帮我算出圆周率小数点后n(n<=10000)位,速度……”然后就挂了电话,也不知道月落乌啼正准备去上课。月落乌啼只好请到了你,让你编一个程序求出圆周率小数点后n位。

输入格式

只有一行:n

输出格式

若干行。

第一行:3.

第二行开始:圆周率的小数部分。10个数一个空格,50个数一次回车。

输入输出样例
输入 #1复制
100
输出 #1复制
3.
1415926535 8979323846 2643383279 5028841971 6939937510
5820974944 5923078164 0628620899 8628034825 3421170679

说明/提示

对于 30%30% 的数据,n\leq 10^3n≤10
3

对于 100%100% 的数据,n\leq 10^4n≤10
4

时限:1\sim 61∼6 点 11 秒,77 点 33 秒,88 点 88 秒,9\sim 109∼10 点 1212 秒。

上代码:

#include<cstdio>
using namespace std;
struct df
{
	long long num[1011];
	int head;
	int tail;
};
int n=0;
df pi={},a={},b={};
void out(df a)
{
	printf("%lld.\n",a.num[0]);
	for(int i=1;i<=n/10;i++)
	{
		printf("%010lld",a.num[i]);
		if(i%5==0)printf("\n");
		else printf(" ");
	}
	switch(n%10)
	{
		case 0:printf("");break;
		case 1:printf("%01lld",a.num[n/10+1]/1000000000ll);break;
		case 2:printf("%02lld",a.num[n/10+1]/100000000ll);break;
		case 3:printf("%03lld",a.num[n/10+1]/10000000ll);break;
		case 4:printf("%04lld",a.num[n/10+1]/1000000ll);break;
		case 5:printf("%05lld",a.num[n/10+1]/100000ll);break;
		case 6:printf("%06lld",a.num[n/10+1]/10000ll);break;
		case 7:printf("%07lld",a.num[n/10+1]/1000ll);break;
		case 8:printf("%08lld",a.num[n/10+1]/100ll);break;
		case 9:printf("%09lld",a.num[n/10+1]/10ll);break;
	}
	if(n%50)printf("\n");
	return;
}
df plus(df a,df b)
{
	df c={};
	long long t=0;
	bool zero=true;
	c.tail=a.tail>b.tail?a.tail:b.tail;
	c.head=(a.head<b.head?a.head:b.head)-1;
	if(c.head<0)c.head=0;
	for(int i=c.tail;i>=c.head;i--)
	{
		c.num[i]=a.num[i]+b.num[i]+t;
		if(c.num[i])zero=false;
		t=c.num[i]/10000000000ll;
		c.num[i]%=10000000000ll;
	}
	if(zero)
	{
		c.head=c.tail;
		return c;
	}
	while(c.num[c.head]==0)c.head++;
	while(c.num[c.tail]==0)c.tail--;
	return c;
}
df minus(df a,df b)
{
	df c={};
	long long t=0;
	bool zero=true;
	c.tail=a.tail>b.tail?a.tail:b.tail;
	c.head=a.head<b.head?a.head:b.head;
	for(int i=c.tail;i>=c.head;i--)
	{
		c.num[i]=a.num[i]-b.num[i]+t;
		if(c.num[i])zero=false;
		if(c.num[i]<0)
		{
			c.num[i]+=10000000000ll;
			t=-1;
		}
		else
			t=0;
	}
	if(zero)
	{
		c.head=c.tail;
		return c;
	}
	while(c.num[c.head]==0)c.head++;
	while(c.num[c.tail]==0)c.tail--;
	return c;
}
df divided(df a,long long b)
{
	df c={};
	long long t=0;
	bool zero=true;
	c.head=a.head;
	c.tail=a.tail;
	for(int i=c.head;i<=c.tail;i++)
	{
		c.num[i]=(a.num[i]+t)/b;
		if(c.num[i])zero=false;
		t=(a.num[i]+t)%b*10000000000ll;
		if(t&&i==c.tail&&c.tail<n/10+10)c.tail++;
	}
	if(zero)
	{
		c.head=c.tail;
		return c;
	}
	while(c.num[c.head]==0)c.head++;
	return c;
}
void set()
{
	a.num[0]=16ll,a.head=0,a.tail=0;
	b.num[0]=4ll,b.head=0,b.tail=0;
	a=divided(a,5);
	b=divided(b,239);
	return;
}
int main()
{
	scanf("%d",&n);
	set();
	long long i=1;
	while(a.head!=n/10+10)
	{
		pi=plus(pi,divided(a,i));
		pi=minus(pi,divided(b,i));
		a=divided(a,25);
		b=divided(b,57121);
		i+=2;
		pi=minus(pi,divided(a,i));
		pi=plus(pi,divided(b,i));
		a=divided(a,25);
		b=divided(b,57121);
		i+=2;
	}
	out(pi);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值