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

Number Length

Problem description
N! (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)
Input
Each line of the input will have a single integer N on it 0 < N < 1000000 (1 million). Input is terminated by end of file.
Output
For each value of N, print out how many digits are in N!.
Sample Input
1
3
32000
1000000
Sample Output
1 
1
130271
5565709
 
看到求阶乘的题目,第一反应就是用递归了,可是注意到这里的输入范围是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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值