斯特林公式与阶乘

想必大家都知道n!很容易爆long long吧,n = 23时(unsigned long long)也束手无策。但很多时候我们又要用到n!。


 一. 斯特灵公式:

这个公式的证明用到了高数极限的知识和Wallis公式,这里就不再赘述。再看斯特林公式的更准确的表达:,n越大,n!越准确,实际上n比较小时,斯特林公式也很近似。


1) 牛客网:https://www.nowcoder.com/acm/contest/75/A

题意:求n!在8进制下的位数。

思路:我们求一个10进制数的位数时怎么求,log10(n)+1就是答案。同理,log8(n!)+1就是此题的解。

AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#define e exp(1)
using namespace std;
double pi=acos(-1.0);
int main()
{
    int n,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        if(n==0)
        {
            puts("1");
            continue;
        }
        int ans= (log10(2*n*pi)/2+n*log10(n/e))/log10(8) ;//对数的性质+斯特灵公式
        printf("%d\n",ans+1);
    }
    return 0;
}

2)牛客网:https://www.nowcoder.com/acm/contest/185/F 

题意很清楚。

思路:用斯特灵公式表示n!,对两边去对数,再二分找n值。

AC代码:

#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
double e = exp(1);
double pi=acos(-1.0);
inline double Stirling(ll n)      //斯特灵公式取对数
{
    return log(2*n*pi)/2+n*log(n/e);
}
int main()
{
    ll x;
    while(cin>>x)
    {
        double tep = x*log(x);  //对x^x对数,等式左右都取对数并不影响结果
        ll l=x,r=2*x;           //二分的左右边界,根据 x! < x^x < (2*x)!而来
        while(1)
        {
            ll mid=(l+r)/2;
            if(Stirling(mid-1)<tep&&Stirling(mid)>tep) mid-1小于,并且mid大于,mid一定是最小
            {
                cout<<mid<<endl;
                break;
            }
            if(Stirling(mid)<tep) l=mid+1;
            else r=mid-1;
        }
    }
    return 0;
}

二.  总结:

n!很大,我们可以用斯特林公式对其取对数,再来计算;切记这只是个近似值。

猜你喜欢

转载自blog.csdn.net/qq_41157137/article/details/82563684