• BZOJ 3000(Big Number-Stirling公式求n!近似值)


    3000: Big Number

    Time Limit: 2 Sec  Memory Limit: 128 MB
    Submit: 220  Solved: 62
    [Submit][Status]

    Description

    给你两个整数N和K,要求你输出N!

    的K进制的位数。

    Input

    有多组输入数据。每组输入数据各一行,每行两个数——N。K

    Output

           每行一个数为输出结果。

    Sample Input

    2 5

    2 10

    10 10

    100 200



    Sample Output

    1

    1

    7

    69




    对于100%的数据,有2≤N≤2^31, 2≤K≤200。数据组数T≤200。

    HINT

    Source


    本题须要用到Stirling公式


    ∴位数=log10(n!)+1

    方案1:[WA]n!

    不断div k

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<functional>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<ctime>
    using namespace std;
    #define For(i,n) for(int i=1;i<=n;i++)
    #define Fork(i,k,n) for(int i=k;i<=n;i++)
    #define Rep(i,n) for(int i=0;i<n;i++)
    #define ForD(i,n) for(int i=n;i;i--)
    #define RepD(i,n) for(int i=n;i>=0;i--)
    #define Forp(x) for(int p=pre[x];p;p=next[p])
    #define Lson (x<<1)
    #define Rson ((x<<1)+1)
    #define MEM(a) memset(a,0,sizeof(a));
    #define MEMI(a) memset(a,127,sizeof(a));
    #define MEMi(a) memset(a,128,sizeof(a));
    #define INF (2139062143)
    #define F (100000007)
    long long mul(long long a,long long b){return (a*b)%F;}
    long long add(long long a,long long b){return (a+b)%F;}
    long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
    typedef long long ll;
    typedef long double ld;
    ld log(ll a,int b){}
    int main()
    {
    //	freopen("bzoj3000.in","r",stdin);
    //	freopen(".out","w",stdout);
    	ll n;int k;
    	while (scanf("%lld%d",&n,&k)!=EOF)
    	{
    		if (n<=10000)
    		{
    			ll ans=0,p=1;
    			Fork(i,2,n) 
    			{
    				p*=i;
    				while (p>=k) {p/=k,ans++;}
    				cout<<i<<':'<<p<<' '<<ans<<endl;
    			}
    			if (p) ans++;
    			printf("%lld
    ",ans);
    		}		
    	}
    	
    	
    	return 0;
    }
    
    可是这样做是错的。TNT

    理由是不断div k 会把原来小的部分删掉


    方案2:logk(n!)=log(1)+log(2)+...+log(n)

    效率为O(n),显然也不行

    于是最好还是用Stirling公式求近似值

    位数=logk(n!)+1

    ≈ logk(sqrt(2πn)*(n/e)^n+1

    = logk(sqrt(2πn))+log[(n/e)^n]+1

    =1/2*logk(2πn)+nlog(n/e)+1

    =0.5*logk(2πn)+nlog(n/e)+1

       =0.5*logk(2πn)+nlog(n)-nlog(e)+1

    PS:pi=acos(-1.0),e=exp(1)

    PS2:eps的存在是为了防止n=2,k=2这样刚好的情况出现,这个时候向上取整要多取1位


    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<functional>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<ctime>
    using namespace std;
    #define For(i,n) for(int i=1;i<=n;i++)
    #define Fork(i,k,n) for(int i=k;i<=n;i++)
    #define Rep(i,n) for(int i=0;i<n;i++)
    #define ForD(i,n) for(int i=n;i;i--)
    #define RepD(i,n) for(int i=n;i>=0;i--)
    #define Forp(x) for(int p=pre[x];p;p=next[p])
    #define Lson (x<<1)
    #define Rson ((x<<1)+1)
    #define MEM(a) memset(a,0,sizeof(a));
    #define MEMI(a) memset(a,127,sizeof(a));
    #define MEMi(a) memset(a,128,sizeof(a));
    #define INF (2139062143)
    #define F (100000007)
    long long mul(long long a,long long b){return (a*b)%F;}
    long long add(long long a,long long b){return (a+b)%F;}
    long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
    typedef long long ll;
    typedef long double ld;
    ld const pi=acos(-1.0),e=exp(1),eps=1e-10;
    ld log(ld a,ld b){return log(a)/log(b);}
    int main()
    {
    //	freopen("bzoj3000.in","r",stdin);
    //	freopen(".out","w",stdout);
    	ll n;int k;
    	cout.setf(ios::fixed);
    	cout.precision(0);
    	
    	while (scanf("%lld%d",&n,&k)!=EOF)
    	{
    		if (n<=10000)
    		{
    			ld ans=0.0;
    			For(i,n) ans+=log(i);
    			ans/=log(k);
    			ans=ceil(ans+eps);
    			cout<<ans<<endl;
    		}		
    		else 
    		{
    			cout<<ll(0.5*log(2*pi*n,k)+n*log(n,k)-n*log(e,k))+1<<endl;
    		}
    		
    	}
    	
    	
    	return 0;
    }
    








  • 相关阅读:
    关于client浏览器界面文字内容溢出用省略号表示方法
    Oracle 11gR2光钎链路切换crs服务发生crash
    制作U盘启动盘将Ubuntu 12.04升级为14.04的方法
    Android图片处理——压缩、剪裁、圆角、保存
    安卓使用WebView下载文件,安卓实现软件升级功能
    Android仿Win8界面的button点击
    Chormium线程模型及应用指南
    POJ 3436 ACM Computer Factory 最大流
    hdu 3547 DIY Cube (Ploya定理)
    ant安装配置问题:ANT_HOME is set incorrectly or ant could not be located. Please set ANT_HOME.
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6782249.html
Copyright © 2020-2023  润新知