斯特林公式近似求阶乘的位数

题目来源:https://www.nowcoder.net/acm/contest/75/A

这条公式不可以直接用,有一个原因:

编者写了一个程序去测试斯特林公式(其实它至少约等于)发现随着输入数的增大,用斯特林公式求出来的近似值误差越来越大。纯粹的斯特林公式只是求一个近似值!!

所以两边取对数:log8(n!) 约等于 log8(斯特林公式),再次测试:

log8(n!)随着n的增大和右式几乎一样。尤其是他们的整数部分,一样的。

这里输入1 和输入50,发现有异常:输入50的时候阶乘公式已经不可以使用了在过程中发生了溢出(fib这个函数内部,事实上阶乘公式算到最多算到20!);输入1时右式为负数可以不用管。因为可以单独拿出来讨论。

k2具体推法就是简单的数学运算问题。不过由于计算机只有log10()//求以10为底的对数和log()//求以e为低对数

所以要用到换底公式。

斯特林公式推出来的意义是?:避免了计算过程中发生溢出。仔细观察double k2发现它的右式里面的数都能用long long存,不会溢出。

最后输出的结果是对k2取整再加1:

#include<stdio.h>
#include<math.h>
#define pi 3.1415926535897932384626
#define e 2.718281828459045235360287471352662497757
int i;
int main()
{
    int n;
    int t;
    scanf("%d",&t);
    while(t--)
    {
         scanf("%d",&n);
         long long m=0;
         double k2=0.5*log10(2*pi)/log10(8)+(n+0.5)*log10(n)/log10(8)-n*log10(e)/log10(8);
         if(k2<1)
            printf("1\n");
         else
         {
            m=(long long)k2;
            printf("%d\n",m+1);
         }

     }
        return 0;
}

十进制转8进制就是不停的除以8并取余,除到最后得到一个数在1到7直接,再除8就为0,余数为本身。

既然是用的log8n!这个公式,(n!)不停除以8就想当于log8(n!)不停地减一。直到最后,该式<1

这表明n!除以k个8以后,变为一个1到7之间的整数。

最后结果就是k+1;

我们要求的即为k+1。

另外,别忘了,把n!<8的请客拿出来单独讨论,即k2<1这种情况。




猜你喜欢

转载自blog.csdn.net/pipitongkw1/article/details/79255665
今日推荐