题目链接:51nod1130
求位数公式是 log10(n)+1 然后此题让求的是n的阶乘的位数
那么很多同学会想到 log0(N!)=log10(1*2*3...*N)+1 = log10(1)+log(2)+log(3)+....+log(N)+1
但是这道题N最大是1e9 所以这种方法肯定会超时 所以我们需要用新的方法
斯特林公式能够近似的求出n的阶乘的值 然后我们再用 求位数公式 log10(n)+1就可以求出答案
斯特林公式 sqrt( 2*pi*n ) * pow( n/e , n)
斯特林公式
而且 log10()内的乘法 又可以转化为加法 那么我们就可以对斯特林公式优化为
0.5 * log10( 2*PI*n ) + n*log10( n/e )
要注意 公式里用到了 e 和 π 我们定义他们有两种写法
#define PI acos(-1.0)
#define E exp(1.0)
const double e = 2.718281828459;
const double pi = 3.1415926535;
建议大家使用第一种
exp()是e的指数幂 括号内是double型 返回值也是double e(1.0)=e^1=e ,e(-1.0)=e^-1
acos()是反三角函数 括号内是double型 返回值也是double acos(-1.0)=π
尤其是这道题 数据特别的卡 刚开始 我定义e =2.71828182845; 疯狂的wa wa了七八遍后 我又多加了一位e =2.718281828459 就对了。。。
所以 由于有的时候 我们不知道数据需要几位 用赋值的定义方式就可能出错
代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
#define PI acos(-1.0)
#define E exp(1.0)
const double e = 2.718281828459;
const double pi = 3.1415926535;
int T;
double n;
int main(){
scanf("%d",&T);
while(T--){
scanf("%lf",&n);
ll ans=(ll)(0.5*log10(2*PI*n) + n*(log10(n/E)) +1);
printf("%I64d\n",ans);
}
return 0;
}