阶乘和

阶乘和
    总时间限制: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 }

 

http://noi.openjudge.cn/ch0106/10/

 

你可能感兴趣的:(阶乘和)