N!的位数
Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Submit
Status
Description
我们知道n!=n*(n-1)(n-2)…*2*1。
那么给定一个n,n!是几位数呢。
更困难的,n!的k进制数有多少位呢。
Input
第一行是一个数T(1≤T≤50000),代表T组测试数据。
每一组测试数据占一行,有两个整数n(0 ≤ n ≤ 10^6),k(2≤k≤1000)。
Output
对于每组测试数据,输出n!k进制数的位数。
Sample Input
2
3 10
3 2
Sample Output
1
3
我们都知道10进制下一个数x的位数为(int)log10(x)+1(不信的话,你可以找几个数来看看) ,所以类比得 k进制下一个数的位数为(int)logk(x)+1 。
现在要求一个数的阶乘的k进制下的位数。即 ( int )logk(x!) + 1
思路一:打表
因为计算机中没有以任何数为底的对数运算,所以我们要先换底公式
logk(x!) +1 = log(x!) / log(k) +1
log(x!) =log(1.0)+log(2.0)+log(3.0) .… .+log(x.0);
然后合并最后的 答案
ans = ( int ) ( (log(x!) =log(1.0)+log(2.0)+log(3.0) .… .+log(x.0)) / log(k) )+1
但是每次运算都要从1算到x,太费时间了,所以我们可以打表,以空间换时间。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#define CLR(a,b) memset((a),(b),sizeof(a))
#define inf 0x3f3f3f3f
#define mod 100009
#define LL long long
#define M 10000000
#define ll o<<1
#define rr o<<1|1
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;
void read(int &x){
x=0;char c;
while((c=getchar())<'0');
do x=x*10+c-'0';while((c=getchar())>='0');
}
double a[M];
void dabiao()
{
double d=0;
a[0]=0.0;
for(int i=1;i<M;i++)
{
d+=log(i);
a[i]=d;
}
}
int main()
{
dabiao();
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
printf("%d\n",int(a[n]/log(m))+1);
}
return 0;
}
思路二 : ( int )logk(x!) + 1
用斯特林公式
斯特林公式 为: N! = sqrt(2 * PI * n ) * ( n / e ) ^n
还是首先用换底公式
logk(x!) = log(x!) / log(k)
然后将 n!的近似公式带入得
ans = ( 0.5 * log ( 2 * PI * n ) + n * log( n / e ) )/ log(k) + 1
这样的话就可以 o(1) 得 。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N =1e6+11;
const int M = 2e6+11;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double E = exp(1.0);
int main(){
// cout<<PI<<"\n";
int t ;scanf("%d",&t);
while(t--){
double n,k;scanf("%lf%lf",&n,&k);
double ans=0.5*log(2*PI*n)+n*log(n/E);
ans/=log(k);
if(n==0) printf("%d\n",1);
else printf("%d\n",int(ans)+1);
}
return 0;
}