洛谷——阶乘之和(大数加、大数乘)

题目描述

用高精度计算出S=1!+2!+3!+…+n!(n≤50)S=1!+2!+3!+…+n! (n≤50)S=1!+2!+3!+…+n!(n≤50)

其中“!”表示阶乘,例如:5!=5×4×3×2×15!=5 \times 4 \times 3 \times 2 \times 15!=5×4×3×2×1。

输入格式

一个正整数NNN。

输出格式

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

输入输出样例

输入 #1

3

输出 #1

9

题意描述

题意很简单就是输入一个数计算从1到这个数的阶乘之和。即1!+2!+3!+.......+n!

解题思路

先算出每个数的阶乘,再将其累加到一个数组上即可。

错误分析

刚开始没有看清题意就开始写了,我就只算了n!,没有进行累加。原来这题是大数加加大数乘,唉,大意了。

下面是代码分为有注释和无注释的,因为有注释的有点乱所以整理一个简洁版

有注释代码

#include<stdio.h>
#include<math.h>
#include<string.h>
int a[100000];
int b[100000];
int c[200000];
int sum[30000]; 
int Factorial(int m,int n){				//两个字符串相乘函数 
	for(int i=0;i<m;i++)
		for(int j=0;j<n;j++){			//数组相乘 
			c[i+j]+=a[i]*b[j];
//			printf("%d %d %d*\n",a[i],b[j],c[i+j]);
		}
	for(int i=0;i<m+n-1;i++)			//处理进位问题 
		if(c[i]>=10){
			c[i+1]+=c[i]/10;
			c[i]%=10;
//			printf("%d ",c[i]);
		}
//	for(int i=0;i<m+n;i++)
//		printf("%d ",c[i]);
//	printf("******************\n");
	int k=m+n;							//估计相乘后数组的位数 
	while(c[k]==0 && k>0)				//从后往前找第一个不为0的数的位置,注意至少有一,毕竟0也是一位数 
		k--;
	for(int i=0;i<=k;i++)				//为了下次相乘,将相乘的结果保存到b数组中 
		b[i]=c[i];

	for(int i=0;i<=k;i++)				//将结果数组清0,不然下次无法计算 
		c[i]=0;
//	printf("%d*\n",k);
	return k+1;							//返回结果数组的长度 
}

int add(int m,int n)					//两个字符串累加函数 
{
	int i=0,j=0;
	if(m>=n){							//找到一个比较长的数组长度,进行相加,如果短的没法全部计算,结果就不对了 
		for(i=0;i<m;i++)				//相加 
			sum[i]+=b[i];
		for(i=0;i<m;i++)				//处理进位 
			if(sum[i]>=10){
				sum[i+1]+=sum[i]/10;
				sum[i]%=10;
			}	
	}	
	else{
		for(i=0;i<n;i++)				//相加 
			sum[i]+=b[i];
		for(i=0;i<m;i++)				//处理进位 
			if(sum[i]>=10){
				sum[i+1]+=sum[i]/10;
				sum[i]%=10;
			}	
	}
	if(sum[i+1]!=0) return i+1;			//返回相加后的数组的长度。 
	else return i;
} 
int main()
{
	int i,j,k,m,n=1,t,x=1,y=1;
	scanf("%d",&t);
	b[0]=1;								//注意相乘的第一位一定为1,不然任何数乘0都为0 
	for(i=1;i<=t;i++)
	{
		k=i;j=0;m=0;
		while(k){						//计算需要相乘的数字的长度,并逆向存入数组中 
			m++;
			a[j++]=k%10;
			k=k/10;
		}
//		printf("%d  %d**\n",m,n);
//		for(x=0;x<m;x++) printf("%d",a[x]);printf("\n");
//		for(x=0;x<n;x++) printf("%d",b[x]);printf("\n");
		x=Factorial(m,x);				//调用相乘函数,传递两个数组的长度 
		y=add(x,y);						//调用相加函数,传递两个数组的长度 
		
//		printf("%d %d**\n",m,n);
	}
//	for(i=x-1;i>=0;i--)
//		printf("%d",b[i]);
//	printf("\n");
//	printf("\n");
	for(i=y-1;i>=0;i--)					//输出结果 
		printf("%d",sum[i]);
	return 0;
}

无注释代码

#include<stdio.h>
#include<math.h>
#include<string.h>
int a[100000],b[100000],c[200000],sum[30000]; 
int Factorial(int m,int n){				 
	for(int i=0;i<m;i++)
		for(int j=0;j<n;j++)			 
			c[i+j]+=a[i]*b[j];

	for(int i=0;i<m+n-1;i++) 
		if(c[i]>=10){
			c[i+1]+=c[i]/10;
			c[i]%=10;
		}

	int k=m+n;							
	while(c[k]==0 && k>0)				
		k--;
	for(int i=0;i<=k;i++)				
		b[i]=c[i];

	for(int i=0;i<=k;i++)				
		c[i]=0;

	return k+1;							
}

int add(int m,int n)
{
	int i=0,j=0;
	if(m>=n){
		for(i=0;i<m;i++)				
			sum[i]+=b[i];
		for(i=0;i<m;i++)
			if(sum[i]>=10){
				sum[i+1]+=sum[i]/10;
				sum[i]%=10;
			}	
	}	
	else{
		for(i=0;i<n;i++)
			sum[i]+=b[i];
		for(i=0;i<m;i++)
			if(sum[i]>=10){
				sum[i+1]+=sum[i]/10;
				sum[i]%=10;
			}	
	}
	if(sum[i+1]!=0) return i+1; 
	else return i;
} 
int main()
{
	int i,j,k,m,n=1,t,x=1,y=1;
	scanf("%d",&t);
	b[0]=1;
	for(i=1;i<=t;i++)
	{
		k=i;j=0;m=0;
		while(k){
			m++;
			a[j++]=k%10;
			k=k/10;
		}
		x=Factorial(m,x);
		y=add(x,y);	
	}
	for(i=y-1;i>=0;i--)	
		printf("%d",sum[i]);
	return 0;
}

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BayMin0520

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值