BZOJ3000. Big Number

题目

给你两个整数N和K,要求你输出N!的K进制的位数。

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

分析

发现其实就是让我们求 (log_k{n!}) 的位数。

暴力求就是 (ans=log_k{1}+log_k{2}+log_k{3}+...+log_k{n})

然后这里有一个斯特林公式可以快速估算这个结果,数字越大越准确。

这个可以变成:

然后直接取 (log) 即可。

数字小的时候我们暴力,大了就斯特林公式。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define inc(x,y,mod) (((x)+(y))>=(mod)?(x)+(y)-(mod):(x)+(y))
#define dec(x,y,mod) ((x)-(y)<0?(x)-(y)+(mod):(x)-(y))
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define per(i,y,x) for(int i=(y);i>=(x);i--)
#define pc putchar
#define PII pair<int,int>
#define fi first
#define se second
#define db double
#define mem(x,k) memset(x,k,sizeof(x))
#define mec(x,y) memcpy(x,y,sizeof(x))
#define close ios::sync_with_stdio(false)
template<typename T>inline void cmax(T& a,const T b){a<b?a=b:0;}
template<typename T>inline void cmin(T& a,const T b){a>b?a=b:0;}
const int N=1e5+5,M=2e5+5,MOD=998244353,INF=1e9+7;
ll n,k;
const db Pi=acos(-1),e=exp(1.0);
signed main(){
	close;
	while(~scanf("%lld%lld",&n,&k)){
		if(n<=100000){
			db ans=0;
			rep(i,2,n) ans+=log(i)/log(k);
			cout<<(ll)(1+ans)<<endl;
		}
		else{
			db ans=0.5*log(2*Pi*n)/log(k)+n*log(n/e)/log(k);
			cout<<(ll)(floor(ans))+1<<endl;
		}
	}
	
	return 0;
}

总结

这个公式用于估算阶乘值的大小,更常用于估算其位数。

原文地址:https://www.cnblogs.com/Akmaey/p/14905956.html