洛谷【P1009】阶乘之和

题目传送门:https://www.luogu.org/problemnew/show/P1009

高精度加法:https://www.cnblogs.com/AKMer/p/9722610.html

之所以在运算法则这个分组的最后一篇博客写这道题是因为之前没写过高精乘低精,也没讲过压位。

所谓压位,就是每一位不只存一位数,比如\(1000009\)分成\(1\)\(0\)\(9\)来存,就只需要三位就能存了。然后\(10\)进制改成\(1000\)进制就行了。

时间复杂度:\(O(len^2)\)

空间复杂度:\(O(len)\)

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int pps=1000;

int n;

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

struct Bignum {
	int num[54];

	void clear() {
		memset(num,0,sizeof(num));
		num[0]=num[1]=1;
	}

	Bignum operator*(const int &a)const {
		Bignum c;memset(c.num,0,sizeof(c.num));
		c.num[0]=num[0];
		for(int i=1;i<=num[0];i++) {
			c.num[i]+=num[i]*a;
			c.num[i+1]+=c.num[i]/pps;
			c.num[i]%=pps;
		}
		if(c.num[c.num[0]+1])c.num[0]++;
		return c;
	}//高精乘低精

	Bignum operator+(const Bignum &a)const {
		Bignum c;memset(c.num,0,sizeof(c.num));
		c.num[0]=max(num[0],a.num[0]);
		for(int i=1;i<=c.num[0];i++) {
			c.num[i]+=num[i]+a.num[i];
			c.num[i+1]+=c.num[i]/pps;
			c.num[i]%=pps;//pps进制,直接强上就行了。
		}
		if(c.num[c.num[0]+1])c.num[0]++;
		return c;
	}

	void print() {
		printf("%d",num[num[0]]);
		for(int i=num[0]-1;i>0;i--)
			printf("%03d",num[i]);//记得不足3为前导补0
	}
}ans;

int main() {
	n=read();
	for(int i=1;i<=n;i++) {
		Bignum res;res.clear();
		for(int j=1;j<=i;j++)
			res=res*j;//算阶乘
		ans=ans+res;//累加
	}ans.print();
	return 0;
}
posted @ 2018-09-29 21:08  AKMer  阅读(285)  评论(0编辑  收藏  举报