HDOJ 1047解题报告
练习ACM后的第一篇解题报告。
这题是求大数阶乘的,题目要求最大能求10000的阶乘。
刚一看到这题,感觉思路很简单,思考了一会之后就开始写代码。思路很简单,由于是大数乘法,普通的int类型肯定不够用,要用数组保存。然后运算过程就是最简单的乘法运算过程,乘--》移位--》加 的简单过程。 提交之后一直是TLE,悲剧,百思不得其解。
随后百度了下,发现应该用“多位一存”,而不是一位一存,(没系统的学习过ACM基础教程,全靠自学,就是悲催!)。采用多位一存,不仅可以加快运算速度,同时也节省了内存。我采用的是四位一存,只需要原来四分之一的控件就可用存下运算结构。运算过程也做了改进,用乘数直接乘以被乘数,而不是蠢蠢的按找小学算术那样一位一位来算。
贴下AC的代码:
1 #include<stdio.h> 2 #include<string.h> 3 int main(void) 4 { 5 int len,k,i,j,r,addin,a[10000],n; //对于10000的阶乘,数组开到一万就够,可以存40000个数字 6 while(scanf("%d",&n)!=EOF) 7 { 8 memset(a,0,sizeof(a)); 9 a[0]=1; 10 for(i=2;i<=n;i++) 11 { 12 for(j=9999;j>=0;j--) //为便于运算,数据是倒着存的,低位在前高位在后,故每次运算都要从后到前找到最高位 13 if(a[j]!=0) 14 break; 15 r=++j; //取r为j后一位,便于进行进位运算 16 addin=0; 17 for(j=0;j<=r;j++) //循环乘,进位 18 { 19 k=a[j]*i+addin; 20 addin=k/10000; 21 a[j]=k%10000; 22 } 23 } 24 for(i=9999;i>=0;i--) //找到最高位,输出,输出的时候注意格式,除了最高位,剩下的要四位一输出 25 if(a[i]!=0) 26 break; 27 printf("%d",a[i]); 28 for(j=i-1;j>=0;j--) 29 printf("%04d",a[j]); 30 printf("\n"); 31 } 32 return 0; 33 }
多位一存对大数乘法运算是非常高效。遇到此类题目,要优先考虑多位一存。