[NOIP1998 普及组] 阶乘之和

[NOIP1998 普及组] 阶乘之和

题目描述

用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!++n! n ≤ 50 n \le 50 n50)。

其中 ! 表示阶乘,定义为 n ! = n × ( n − 1 ) × ( n − 2 ) × ⋯ × 1 n!=n\times (n-1)\times (n-2)\times \cdots \times 1 n!=n×(n1)×(n2)××1。例如, 5 ! = 5 × 4 × 3 × 2 × 1 = 120 5! = 5 \times 4 \times 3 \times 2 \times 1=120 5!=5×4×3×2×1=120

输入格式

一个正整数 n n n

输出格式

一个正整数 S S S,表示计算结果。

样例 #1

样例输入 #1

3

样例输出 #1

9

提示

【数据范围】

对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1n50

【其他说明】

注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n ≤ 20 n \le 20 n20,使用书中的代码无法通过本题。

如果希望通过本题,请继续学习第八章高精度的知识。

题解

高精度加法

Created with Raphaël 2.3.0 开始 将两个字符串reverse,再相加; 将所得的值赋给特定的字符串数组; 结束 yes
void awithb(){     //求和; 
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(e,0,sizeof(e));
	int sum1=strlen(sum);
	int a1=strlen(a);
	if(sum1==0){
		strcpy(sum,a);
	}
	else{
for(int i=a1-1,j=0;i>=0;i--,j++){  //c=a;
	c[j]=a[i]-'0';
}
for(int i=sum1-1,j=0;i>=0;i--,j++){
	d[j]=sum[i]-'0';
}	
int max=a1;
if(sum1>a1)max=sum1;
for(int i=0;i<=max;i++){
	e[i]+=c[i]+d[i];
	if(e[i]>=10){
		e[i+1]++;
		e[i]=e[i]%10;
	} 
}
memset(sum,'0',sizeof(sum));
int f=0,j,i;
if(e[max]!=0){
	sum[0]=e[max]+'0';
	f++;
}
for(i=max-1,j=f;i>=0;i--,j++){
	sum[j]=e[i]+'0';
}
sum[j]='\0';
	}
}

高精度乘法

Created with Raphaël 2.3.0 开始 将两个字符串reverse,再相乘; 赋给特定的数组 结束 yes
    1 0 9
   *  9 9
   ————————
    9 8 1
+ 9 8 1
 ——————————————
  1 7 9 1
/*我们只要将他翻转过来;选择其中一位数,当另一个每进一位;
  我们就将选定的那个数也进一位;
*/
for(z=0,k=0;z<max;z++,k++){
	for(j=0,s=k;j<max;j++,s++){
	e[s]+=c[z]*d[j];
	if(e[s]>=10){
	e[s+1]+=e[s]/10;
		e[s]=e[s]%10;	
	}
}
}

高精度阶乘

Created with Raphaël 2.3.0 输入 先相乘,后相加; 确认? 输出 yes
for(int i=1;i<=n;i++){
		memset(a,0,10000);
		for(int j=1;j<=i;j++){
			achenb(j);//求积; 
		}
		awithb();//求和; 
	}
#include<bits/stdc++.h>
#include<cstring>
#include<cstdio> 
using namespace std;
char a[10000],b[10000],sum[10000];
int c[10000],d[10000],e[10000];
void awithb(){     //求和; 
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(e,0,sizeof(e));
	int sum1=strlen(sum);
	int a1=strlen(a);
	if(sum1==0){
		strcpy(sum,a);
	}
	else{
for(int i=a1-1,j=0;i>=0;i--,j++){  //c=a;
	c[j]=a[i]-'0';
}
for(int i=sum1-1,j=0;i>=0;i--,j++){
	d[j]=sum[i]-'0';
}	
int max=a1;
if(sum1>a1)max=sum1;
for(int i=0;i<=max;i++){
	e[i]+=c[i]+d[i];
	if(e[i]>=10){
		e[i+1]++;
		e[i]=e[i]%10;
	} 
}
memset(sum,'0',sizeof(sum));
int f=0,j,i;
if(e[max]!=0){
	sum[0]=e[max]+'0';
	f++;
}
for(i=max-1,j=f;i>=0;i--,j++){
	sum[j]=e[i]+'0';
}
sum[j]='\0';
	}
}
void achenb(int i){ //a=a*b;-->result=a;
memset(b,'0',sizeof(b));
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
memset(e,0,sizeof(e));
sprintf(b,"%d",i);
int a1=strlen(a);
int b1=strlen(b);
int sum=a1*b1;
if(a1==0){
a1=b1;
strcpy(a,b);
}
else{
int j,k,s,t,z;
for(z=a1-1,j=0;z>=0;z--,j++){
	c[j]=a[z]-'0';
}
for(z=b1-1,j=0;z>=0;z--,j++){
	d[j]=b[z]-'0';
}
int max=a1;
if(b1>a1)max=b1;
memset(a,0,sizeof(a));
for(z=0,k=0;z<max;z++,k++){
	for(j=0,s=k;j<max;j++,s++){
	e[s]+=c[z]*d[j];
	if(e[s]>=10){
	e[s+1]+=e[s]/10;
		e[s]=e[s]%10;	
	}
}
}
sum++;
while(sum!=0){
	if(e[sum]!=0)break;
	sum--;
}
for(s=sum,t=0;s>=0;s--,t++){
	a[t]=e[s]+'0';
}}
}
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		memset(a,0,10000);
		for(int j=1;j<=i;j++){
			achenb(j);//求积; 
		}
		awithb();//求和; 
	}
	for(int i=0;i<strlen(sum);i++){
		printf("%c",sum[i]);
	}
	printf("\n");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值