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,太费时间了,所以我们可以打表,以空间换时间。
思路二 : ( 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) 得 。
代码
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; }
相关文章推荐
- 【斯特林公式】N!的k进制位数
- Digits of Factorial (求N!的k进制位数)(打表)
- HDOJ---1018 求N!的位数[斯特林公式---处理阶乘及阶乘位数的问题]
- HDOJ1018 Big Number(斯特林公式求阶乘位数)
- hdu 3032 Nim or not Nim?(打表 sg函数)
- 斯特林公式近似求阶乘的位数
- HDU 3032 Nim or not Nim?(Multi_SG,打表找规律)
- LightOJ - 1045 求N!在k进制下的的位数(斯特林公式)
- HDU 3032 Nim or not Nim?(博弈,SG打表找规律)
- POJ 1423 HDOJ 1018 Big Number(数学—求n!的位数,log取底和斯特林公式的应用)
- hdu 3032 Nim or not Nim? (SG打表找规律)
- bzoj 3000 Big Number 估算n!在k进制下的位数 斯特林公式
- HDOJ3032 Nim or not Nim? (sg打表)
- 【HDU3032】【Lasker's Nim(一种Nim游戏)】Nim or not Nim? Multi-SG博弈、打表
- hdu 3032 Nim or not Nim? (SG函数博弈+打表找规律)
- sugar 自动为DP 加cache (or打表)
- 斯特林公式求大数位数
- HDU 3032 Nim or not Nim? SG打表找规律
- 求n!的位数以及求n!具体的值(C or C++)
- Codeforces Round #315 (Div. 2) C. Primes or Palindromes? (打表枚举)