#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前将进位置0 for (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"); }