Problem Description
In many applications very large integers numbers are required. Some of these applications are using keys for secure transmission of data, encryption, etc. In this problem you are given a number, you have to determine the number of digits in the factorial of the number.
Input
Input consists of several lines of integer numbers. The first line contains an integer n, which is the number of cases to be tested, followed by n lines, one integer 1 ≤ n ≤ 107 on each line.
Output
The output contains the number of digits in the factorial of the integers appearing in the input.
 
Sample Input
2 10 20
Sample Output
7 19
Source
 
Recommend
JGShining   |   We have carefully selected several similar problems for you:  1017 1016 1071 1019 1021 
 
 
/***********************************************************起初的代码*********************************************************************
 
#include<iostream>
#include<cmath>
using namespace std;

int get(int m){
	int pass = 0;        //进位 
	int num[100];        //存储位数 
	num[0] = 1;          //一个数的第几位 
	int count = 0;       //记录进位的位数 
	int s = 0;
	int number = 1;      //记录数目的长度
	 
	for(int i=1;i<=m;i++){    //阶乘 
		for(int j=0;j<number;j++){		 //数组需要操作有数的位置 
		    s = pass;	
			pass = (num[j]*i + pass)/10;  //确定进位 
			num[j] = (num[j]*i + s)%10;	  //确定后一位 
		} 
		s = pass;
       	while(pass > 0)                   //输出进位的位数 可能是1位数 可能是2位数,可能是3位数 。。。。 
		{
            count++;
            pass = pass/10;            
		}
		while(count){
			num[number] = s%10;           //存储进位的值 
			number++;
			s = s/10;
			count--;
		}
        pass = 0;
	}
	return number;                       //返回长度 
}
int main(){
	int n;
	cin>>n;         //输入需要计算数目 
	while(n--){
		int m;
		cin>>m;
		cout<<get(m)<<endl;   //得到每个样例结果 
	}
} 

后面发现对于N!来说是比较快的了,但是对于n = 1000000时仍然会超时,于是乎决定不能这么直接

解题思路:

1.可以暴力,N的阶乖的位数等于LOG10(N!)=LOG10(1)+.....LOG10(N);
2.Stirling公式:n!与√(2πn) * n^n * e^(-n)的值十分接近
故log10(n!) = log(n!) / log(10) = ( n*log(n) - n + 0.5*log(2*π*n))/log(n);
参考的是: http://blog.csdn.net/ultimater/article/details/7884951
 
于是乎比较简单
 
方法1:
#include<iostream>
#include<cmath>
using namespace std;

double get(int m){
    double cnt = 0;
	for(int i=2;i<=m;i++){
		cnt += log10(i);
	}
	return cnt;
}
int main(){
	int n;
	cin>>n;         //输入需要计算数目 
	while(n--){
		int m;
		cin>>m;
		cout<<1+(int)get(m)<<endl;   //得到每个样例结果 
	}
} 

 

方法2:

#include<iostream>
#include<cmath>
using namespace std;
#define PI    3.141592653
#define ln10  log(10.0)

double get(int N){
    double cnt = 0;
    cnt = ceil((N*log(double(N))-N+0.5*log(2.0*N*PI))/ln10);
	return cnt;
}
int main(){
	int n;
	cin>>n;         //输入需要计算数目 
	while(n--){
		int m;
		cin>>m;
		cout<<(int)get(m)<<endl;   //得到每个样例结果 
	}
} 

关于log10()可以参考 : https://msdn.microsoft.com/zh-cn/library/t63833dz.aspx;

关于ceil()函数,向上取整 ,可以参考: https://baike.baidu.com/item/ceil/10931457?fr=aladdin

还是数学公式好,死算的很可能GG

 

 
posted on 2018-01-22 18:54  任我主宰  阅读(138)  评论(0编辑  收藏  举报