阶乘和
阶乘和
总时间限制:1000ms 内存限制:65536kB
描述
用高精度计算出S=1!+2!+3!+…+n!(n≤50)
其中“!”表示阶乘,例如:5!=5*4*3*2*1。
输入正整数N,输出计算结果S。
输入
一个正整数N。
输出
计算结果S。
样例输入
5
样例输出
153
来源 NOIP1998复赛 普及组 第二题
分析:
这个题目涉及大整数的加法、大整数的阶乘。这个地方,大整数阶乘其实是累乘,就是一个大整数乘以一个小整数。
这里大整数可以考虑使用一个int数组模拟,各位数字按低位到高位从数组的第0号元素开始存储。另外使用一个int变量记录该大整数的位数。
这样一来,大整数相加,只要按位相加并处理好进位即可。(为了方便,大整数数组后面没有使用的部分可以都设为0.)
一个大整数temp[ ]和一个int变量t相乘,可以用t变量的每一位依次乘以大整数的各个位,把结果放在另外一个临时数组ansT[ ]中,乘完后再复制到temp[]即可。注意处理好进位即可。
这里要注意:
ansT[j+k]=temp[j]*t+ansT[j+k];
ansT[j+k+1]=ansT[j+k+1]+ansT[j+k]/10;
ansT[j+k]=ansT[j+k]%10;
其中k是指当前参与乘法计算的是t的第k位。(个位是第0位,十位是第1位,其他以此类推。)ansT[]在t*temp[ ]之前要清0.
在此过程要注意更新temp[]的长度。
1 #include <stdio.h> 2 #define maxLen 2000 3 int main(int argc, char *argv[]) 4 { 5 int n,i; 6 int ans[maxLen]={0},temp[maxLen]={0},ansT[maxLen]={0};//低位在前,高位在后 7 int lenA,lenT; 8 9 int j,tempI,t,k,flag,c; 10 11 scanf("%d",&n); 12 if(n==0||n==1) 13 { 14 printf("1\n"); 15 return 0; 16 } 17 else if(n<0) return 0; 18 19 ans[0]=1; // 1的阶乘 20 lenA=1; 21 temp[0]=1; //1的阶乘 22 lenT=1; 23 for(i=2;i<=n;i++)//每轮循环计算出i的阶乘并累加到ans 24 { 25 //计算i的阶乘: temp[]*i -> ansT[] -> temp[]. 26 27 //先实现:temp[]*i -> ansT[].这个需要用i的每一位依次去乘temp[] 28 tempI=i; 29 for(j=0;j<maxLen;j++) ansT[j]=0; 30 k=0; //k表示当前准备用i的第k位去乘temp[] 31 while(tempI>0)//枚举tempI的每一个位的数字 32 { 33 t=tempI%10;//temp[]*t -> ansT[] 34 tempI=tempI/10; 35 for(j=0;j<lenT;j++)//用t去乘以temp[]的每一位 36 { 37 ansT[j+k]=temp[j]*t+ansT[j+k]; 38 ansT[j+k+1]=ansT[j+k+1]+ansT[j+k]/10; 39 ansT[j+k]=ansT[j+k]%10; 40 } 41 k++;//k表示当前t是i的第几位 42 } 43 //这个for的功能:ansT[] -> temp[] 44 flag=0; 45 for(j=maxLen-1;j>=0;j--) 46 { 47 temp[j]=ansT[j]; 48 if(flag==0&&ansT[j]!=0)//寻找temp[]的长度 49 { 50 lenT=j+1; 51 flag=1; 52 } 53 } 54 55 //测试性质的代码:输出temp[] 56 /*for(j=lenT-1;j>=0;j--) 57 { 58 printf("%d",temp[j]); 59 } 60 printf("----------");*/ 61 62 //计算累加和:ans[]+temp[] -> ans[] 63 c=0;//两个位相加时的进位 64 lenA=(lenA>lenT?lenA:lenT); 65 for(j=0;j<lenA;j++) 66 { 67 ans[j]=ans[j]+temp[j]+c; 68 c=ans[j]/10; 69 ans[j]=ans[j]%10; 70 } 71 if(c!=0) 72 { 73 ans[j]=c; 74 lenA++; 75 } 76 //测试性质的代码:输出ans[] 77 /*for(j=lenA-1;j>=0;j--) 78 { 79 printf("%d",ans[j]); 80 } 81 printf("\n");*/ 82 } 83 for(j=lenA-1;j>=0;j--) 84 { 85 printf("%d",ans[j]); 86 } 87 printf("\n");/**/ 88 return 0; 89 }
另一段优秀的代码:

1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int a[100000],n,i,y,xy[100000],s[100000]; 5 6 void add()//s[]=s[]+a[],计算过程用xy[]做临时存储空间 7 { 8 int i; 9 memset(xy,0,sizeof(xy)); 10 xy[0]=max(s[0],a[0]); 11 for (i=1;i<=xy[0];i++) 12 { 13 xy[i]+=s[i]+a[i]; 14 xy[i+1]=xy[i]/10; 15 xy[i]%=10; 16 } 17 while (xy[xy[0]+1]>0) 18 { 19 xy[xy[0]+2]=xy[xy[0]+1]/10; 20 xy[xy[0]+1]%=10; 21 xy[0]++; 22 } 23 s[0]=xy[0]; 24 for (i=1;i<=xy[0];i++) s[i]=xy[i]; 25 } 26 int main() 27 { 28 cin>>n; 29 a[0]=1;a[1]=1;//a[]现在表示1的阶乘 30 s[0]=1;s[1]=0;//s[]现在表示数字0 31 for (y=1;y<=n;y++) //计算1!+2!+3!+……+n! 32 { 33 //第一步:计算y的阶乘y!=(y-1)!*y,其中y-1的阶乘就是a[]。计算结果存储在xy[] 34 memset(xy,0,sizeof(xy)); 35 xy[0]=a[0]; 36 for (i=1;i<=a[0];i++) 37 { 38 xy[i]+=a[i]*y; 39 xy[i+1]=xy[i]/10; 40 xy[i]%=10; 41 } 42 while (xy[xy[0]+1]>0) 43 { 44 xy[xy[0]+2]=xy[xy[0]+1]/10; 45 xy[xy[0]+1]%=10; 46 xy[0]++; 47 } 48 //第二步:将计算结果复制到a[] 49 for (i=1;i<=xy[0];i++) a[i]=xy[i]; 50 a[0]=xy[0]; 51 //第三步:阶乘累加 52 add(); 53 } 54 for (i=s[0];i>=1;i--) cout<<s[i]; 55 cout<<endl; 56 return 0; 57 }
http://noi.openjudge.cn/ch0106/10/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2013-12-09 OpenJudge计算概论-求满足条件的3位数
2013-12-09 OpenJudge计算概论-完美立方【暂时就想到了枚举法了】
2013-12-09 OpenJudge计算概论-简单算术表达式求值
2013-12-09 OpenJudge 计算概论-判断闰年