AOJ 758.大数的位数
大数的位数Time Limit: 1000 ms Case Time Limit: 1000 ms Memory Limit: 64 MB
Total Submission: 30 Submission Accepted: 9Description给出一个整数,确定这个数的阶乘的位数。
Input多组数据,每行为一个大于等于1且小于等于107的整数n.
Output对应每个输入数据输出一个结果。
Sample Input
Original Transformed 10 20
Sample Output
Original Transformed 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)
AC代码:GitHub
1 /* 2 By:OhYee 3 Github:OhYee 4 HomePage:http://www.oyohyee.com 5 Email:oyohyee@oyohyee.com 6 Blog:http://www.cnblogs.com/ohyee/ 7 8 かしこいかわいい? 9 エリーチカ! 10 要写出来Хорошо的代码哦~ 11 */ 12 13 #include <cstdio> 14 #include <algorithm> 15 #include <cstring> 16 #include <cmath> 17 #include <string> 18 #include <iostream> 19 #include <vector> 20 #include <list> 21 #include <queue> 22 #include <stack> 23 #include <map> 24 using namespace std; 25 26 //DEBUG MODE 27 #define debug 0 28 29 //循环 30 #define REP(n) for(int o=0;o<n;o++) 31 32 const int maxn = 10005; 33 bool tree[maxn]; 34 35 int bit(int n) { 36 int a = 1; 37 int e = 0; 38 39 for(int i = 1;i <= n;i++) { 40 a *= i; 41 while(a / 100000) {//保证精度 42 a /= 10; 43 e++; 44 } 45 } 46 47 while(a) {//转化为位数 48 a /= 10; 49 e++; 50 } 51 52 return e; 53 } 54 55 //n! = 1*2*3*4*5*......*(n-1)*n 56 //ln n! = ln 1+len2+......ln(n-1)+ln n 57 int mathbit(int n) { 58 double ans = 0; 59 for(int i = 1;i <= n;i++) 60 ans += log10(i); 61 return (int)ans+1; 62 } 63 64 65 bool Do() { 66 int n; 67 if(scanf("%d",&n) == EOF) 68 return false; 69 70 71 printf("%d\n",mathbit(n)); 72 return true; 73 } 74 75 int main() { 76 while(Do()); 77 return 0; 78 }
然而,我并不能保证我说的是对的。请自行验证,如有错误,请指正
新博客地址
https://www.oyohyee.com
https://www.oyohyee.com