题目
Description
给出一个整数,确定这个数的阶乘的位数。
Input
多组数据,每行为一个大于等于1且小于等于107的整数n.
Output
对应每个输入数据输出一个结果。
Sample Input
10
20Sample Output
7
19
题解
两种方法可能可以实现:
- 抛去一定的精度来计算
- 采用数学公式计算
抛去一定的精度来计算
对于第一种方法,我们可以得知,对于两个大数相乘,其较低位对结果的影响较小,因此我们可以舍弃一些数据
采用类似于科学记数法的形式来计算(a*10^b
)
这种做法,当n较大时,会由于误差的累积导致错误。
采用数学公式计算
而第二种方法可以采用一些数学公式计算
log10n! = log10(1*2*3*......*n) = log101+log102+log103+...+log10n
显然,等式右侧我们可以轻易得出。
而等式左侧,log10n的意义是n对10的对数,即10log10n=n
对于一个整数k,若10k<n<10k+1,我们可以得出结论,n是k位数
所以,大数n!的位数就是log10n!,由于int的向下取整性质,我们还要将这个数再加上1
虽然题目上说的最大值是107,然而,最大值至少是197(方法1WA)
代码
/* By:OhYee Github:OhYee HomePage:http://www.oyohyee.com Email:oyohyee@oyohyee.com Blog:http://www.cnblogs.com/ohyee/ かしこいかわいい? エリーチカ! 要写出来Хорошо的代码哦~ */ #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <vector> #include <list> #include <queue> #include <stack> #include <map> using namespace std; //DEBUG MODE #define debug 0 const int maxn = 10005; bool tree[maxn]; int bit(int n) { int a = 1; int e = 0; for(int i = 1;i <= n;i++) { a *= i; while(a / 100000) {//保证精度 a /= 10; e++; } } while(a) {//转化为位数 a /= 10; e++; } return e; } //n! = 1*2*3*4*5*......*(n-1)*n //ln n! = ln 1+len2+......ln(n-1)+ln n int mathbit(int n) { double ans = 0; for(int i = 1;i <= n;i++) ans += log10(i); return (int)ans+1; } bool Do() { int n; if(scanf("%d",&n) == EOF) return false; printf("%d\n",mathbit(n)); return true; } int main() { while(Do()); return 0; }