大数阶乘

来源:互联网 发布:波士顿矩阵图讲解 编辑:程序博客网 时间:2024/06/08 06:28
#include <stdio.h>#include <stdlib.h>#include <time.h>void Factorial(int n);int main(){int n;clock_t start,finish;double duration;while (printf("\nInput a number:  "),scanf("%d",&n)!=EOF){start=clock();Factorial(n);finish=clock();duration=(double)(finish-start)/CLOCKS_PER_SEC;printf("Time consumed is :  %.2lf\n",duration);}return 0;}void Factorial(int n){int a[100000],tail=0;//tail是最高位的下标int i,j,iCarry;  //iCarry是进位a[0]=1;for (i=2;i<=n;i++){iCarry=0;  //每次*i前将进位置0for (j=0;j<=tail;j++){if (iCarry==0&&a[j]==0) //如果当前位是0并且无进位{continue;}a[j]=a[j]*i+iCarry;  //当前数位*i+进位iCarry=a[j]/10000;   //求新的进位a[j]%=10000;         //更新当前数位}if (iCarry)  //如果超过当前解的长度,将进位添加到解中{a[++tail]=iCarry;}}for (i=tail;i>=0;i--) //输出{printf("%d",a[i]);}printf("\n");}


今天一个偶然的机会,发现这个程序有问题!

不信可以输入8试试,结果为4320,这与正确答案40320相比显然错误!

7!=5040;  此时a[0]=5040;  a[0]*8=40320;   a[0]%=10000后 a[0]=320!!!发现错误了吧!

怎样修改呢?可以使用printf输出固定宽度的数字,不足左补零的方法!

附代码:

#include <stdio.h>void calFac(int n);int main(){int n;while (scanf("%d",&n)!=EOF){calFac(n);}return 0;}void calFac(int n){int iRes[40000],iIndex=0;int iCarry,i,j;iRes[0]=1;for (i=2;i<=n;i++){iCarry=0;for (j=0;j<=iIndex;j++){if (iRes[j]==0&&iCarry==0){continue;}iRes[j]=iRes[j]*i+iCarry;iCarry=iRes[j]/10000;iRes[j]%=10000;}if (iCarry!=0){iRes[++iIndex]=iCarry;}}printf("%d",iRes[iIndex]);for (i=iIndex-1;i>=0;i--){printf("%04d",iRes[i]);}printf("\n");}

有一个一个稳当的算法,但比较慢!(HDU上390MS,上面是1700MS)

#include <stdio.h>void calFac(int n);int main(){int n;while (scanf("%d",&n)!=EOF){calFac(n);}return 0;}void calFac(int n){int iRes[40000],iIndex=0;int iCarry,i,j;iRes[0]=1;for (i=2;i<=n;i++){iCarry=0;for (j=0;j<=iIndex;j++){if (iRes[j]==0&&iCarry==0){continue;}iRes[j]=iRes[j]*i+iCarry;iCarry=iRes[j]/10;iRes[j]%=10;}while (iCarry!=0){iRes[++iIndex]=iCarry%10;iCarry/=10;}}for (i=iIndex;i>=0;i--){printf("%d",iRes[i]);}printf("\n");}