算法学习10146(计算阶乘的位数)

来源:互联网 发布:知乎 放假 编辑:程序博客网 时间:2024/06/04 18:21

Number Length

Problem descriptionN! (N factorial) can be quite irritating and difficult to compute for large values of N. So instead of calculating N!, I want to know how many digits are in it. (Remember that N! = N * (N - 1) * (N - 2) * ... * 2 * 1)
InputEach line of the input will have a single integer N on it 0 < N < 1000000 (1 million). Input is terminated by end of file.
OutputFor each value of N, print out how many digits are in N!.
Sample Input

13320001000000
Sample Output
1 11302715565709
看到求阶乘的题目,第一反应就是用递归了,可是注意到这里的输入范围是1~1000000,而在32位系统中(现在基本上int都是32位),范围-2147483648~+2147483647。unsigned类型 的int 范
围:0~4294967295 即 0~(2的32次方-1),所以用递归把阶乘结果计算出来以后再算位数是会越界的,除非用数组保存阶乘结果,但感觉略麻烦。这里我用了3种方法来计算阶乘的位数:
方法一:直接利用公式计算阶乘结果以及位数:对于数n求位数:log10(n)+1即可,只要注意的是,<math.h>中log10(n)的返回值是double,所以要转换成int。
int main()
{double pi = acos(-1);int n;double temp;int result;while(scanf("%d",&n)&&n!=EOF){temp=n*log(n)-n+0.5*log(2*n*pi);result=(int)(temp/log(10))+1;printf("%d\n",result);}return 0;}
方法二:利用迭代,原本计算公式应该是(n*(n-1)*...*2*1)/(10*10*...*10),计算能除多少个10,结果再加1.现在是从第一个n开始就除10,判断能否除完以后的结果>1,如果大于1,就result++,
把结果继续乘(n-1),再除10,同样计算;如果不能除10,就乘以(n-1)后再判断。
int main(){int n ;while(scanf("%d",&n)!=EOF){int result=1;int i;double temp = 1;for(i=n;i>0;i--){temp*=i;while((temp/10)>1){result++;temp=temp/10;}}printf("%d\n",result);}return 0;}
方法三:使用动态规划的思想,提高速率。将1000000个结果都先保存在result[1000000]数组中,根据log10(n*(n-1)*(n-2)*...*2*1)=log10(n)+log10(n-1)+...+log10(2)+log10(1)的公式,
直接计算出阶乘的位数,所以result[n] = result[n-1]+log10(n);
double result[1000000];//全局变量
void add(int n)
{
if(n==1)        result[1]=log10(1);    else        result[n]=result[n-1]+log10(n);}int main(){    int n;    int length=0;    int i;    double temp;    for(i=1;i<=1000000;i++)        add(i);    while(scanf("%d",&n)!=EOF)    {            length = 1+(int)result[n];        printf("%d\n",length);    }          return 0;}
其实一开始这三种方法怎么试都通不过学校ACM的测试器,一直报超时,困惑了很久,发现原来是死在了输入上!
原先所有方法的循环输入我是这么写的:
while(scanf("%d",&n)&&n!=EOF)
但是正确的输入应该是:
while(scanf("%d",&n)!=EOF)
错误出现在哪里使他死循环了呢?
当读到输入文件的末尾,scanf会返回EOF。scanf要么返回1(成功匹配input),要么返回-1(读到文件末尾),EOF在C的头文件里面是一个宏,
通常的值为-1,但是如果写成n!=EOF,我输入的n的确是永远都不会是-1的,因为输入在1~1000000,也就是当我到达输入文件的末尾时,&&的左右
两项都不会为0,while()内的条件永真,死循环---->超时!

0 0
原创粉丝点击