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

xiaoxiao2021-02-28  102

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; }
转载请注明原文地址: https://www.6miu.com/read-80285.html

最新回复(0)