poj1423是一道纯数学题目,原题的意思是输入一个数1 <= n <= 10^7 ,即需要用long来存储n,然后输出它的阶乘结果的位数。
这道题目的数据庞大,达10^7,高精度模拟显然不行。因此n我们必须另外想方法。
要知道一个数字的位数是多少,我们可以用log10函数求得。例如,对于一个数,N=10,10!=3628800,而log10(3628800)=6.559763033,那么只要将这个数向上取整,就是7,就是10!的位数。
于是我们可以得到 log10(n!)=log10(1*2*3…*n)=log10(1)+log10(2)+…+log10(n)
但是用将一个一个数累加明显很超时,所以不能采用这种方法。
《计算机程序设计艺术》中给出了另一个公式
π = acos(-1)
e = exp(1)
两边对10取对数
忽略log10(1 + 1/(12*n) + 1/(288*n*n) + O(1/n^3)) ≈ log10(1) = 0
得到公式
log10(n!) = log10(sqrt(2 * pi * n)) + n * log10(n / e)。
值得注意的是当n= 1的时候,输出结果为负,取整会为0。所以可以利用if语句来输出n= 1的情况。并且在log10(n!)的结果需要加1,再进行取整。
PS:反三角函数:asin(double) acos(double) atan(double);
自然数e=exp(1.0);
以下是源代码
#include <iostream>
#include <cmath>
using namespace std;
const double pi = acos(-1.0);
const double e = exp(1.0);
int main()
{
int n;
long num;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> num;
if(num == 1)
cout << 1 << endl;
else
cout << int (log10(sqrt(2 * pi * num)) + num * log10(num / e) + 1) << endl; //在log10(n!)的结果加上1,并强制转换类型取整
}
return 0;
}