斯特林公式
简介
斯特林公式的常见表示形式
显而易见,这个公式主要是用来求近似的阶乘的值的,在竞赛中往往只采用第一个形式,其精确度已经足够用来求阶乘位数了.
lg(n!)=lg(2πn)/2+n∗(lg(n)−lg(e))
这个公式就是图中第一个式子左右同时求对数得到的.
不难发现,[10x,10(x+1) )之间囊括了所有长度为x+1的数,而lg(m*10^x)=x+lg(m)
,而lg(m)
一定是小于1的,所以我们只需要看lg(n!)
的整数部分(然后再加1)就可以了.
综上所述
n! == int(floor(log10(2 * PI * n) / 2 + n * (log10(1.0 * n) - loge)))+1
但是要注意!! n==1 或者0 时必须特判才行,1!=1,如果按照此公式,会得到0这个匪夷所思的答案.
POJ 1423
AC 代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define ll long long
#define MAXN 1100
const double e = 2.71828182845;
#define loge log10(e)
#define PI 3.1415926535
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
if (n==0||n == 1) {
printf("1\n");
} else {
int s;
s = int(floor(log10(2 * PI * n) / 2 + n * (log10(1.0 * n) - loge)));
printf("%d\n", s + 1);
}
}
return 0;
}
牛客75A(八进制下阶乘位数)
我尝试直接魔改上面的公式,在后面整体换底,结果失败了(通过了60%的数据),应该是只能在计算对数的时候就算8的底(注:下文的log8并没有内置的函数,是自己写的)
AC代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define ll long long
#define MAXN 1100
double log8(double x) {
return log(x) / log(8);
}
const double e = exp(1);
const double loge = log8(e); // 这个单独定义出来挺鸡肋的,还怕忘了改
const double PI = acos(-1.0);
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
if (n == 1 || n == 0) {
printf("1\n");
} else {
ll s;
// 形式不变
s = (long long) (floor(log8(2 * PI * n) / 2 + n * (log8(1.0 * n) - loge)));
printf("%lld\n", s + 1);
}
}
return 0;
}