您的位置:首页 > 其它

N!的k进制位数 【打表】or【斯特林公式】

2017-05-07 17:16 169 查看
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
/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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: