HDU 1018(阶乘位数 数学)

题意是求 n 的阶乘的位数。

直接求 n 的阶乘再求其位数是不行的,开始时思路很扯淡,想直接用一个数组存每个数阶乘的位数,用变量 tmp 去存 n 与 n - 1 的阶乘的最高位的数的乘积,那么 n 的阶乘的位数就等于 n - 1 的阶乘的位数加 tmp 的位数再减去 1。

 但这种做法是不对的,例如有可能最高位与 n 的乘积结果是 99,而其实 n 与其他位的乘积结果是能进到这一位的,也就是说实际应该在 n - 1 的阶乘位数上增加 2 ( 3 -1 ) 位。而在对样例测试时也发现 n 为 10 的时候结果尚正确,但当 n 为 20 的时候就比正确结果少了 1,也就是说发生了上述情况。

抱着侥幸心理,又再次将每次乘以最高位的做法调整成了每次乘以最高的两位,这一次当 n 为 20 时结果依然正确,但是内存超了......

错误代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int tmp,dig[10000009];
 4 int getdigit(int n)
 5 {
 6     int a(0);
 7     while(n)
 8     {
 9         n/=10;
10         a++;
11     }
12     return a;
13 }
14 void make()
15 {
16     int digit;
17     dig[1] = 1;
18     dig[2] = 1;
19     dig[3] = 1;
20     dig[4] = 2;
21     tmp = 24;
22     for(int i = 5; i <= 10000000; i++)
23     {
24         tmp *= i;
25         digit = getdigit(tmp);
26         dig[i] = digit + dig[i-1] - 2;
27         for(int j = 2; j < digit; j++) tmp/=10;
28     }
29 }
30 int main()
31 {
32     int t,ans,n;
33     scanf("%d",&t);
34     make();
35     while(t--)
36     {
37         scanf("%d",&n);
38         printf("%d
",dig[n]);
39     }
40     return 0;
41 }
View Code

在借鉴了其他人的做法后,才觉得对这道题有了一点正确的思路:

首先,一个数 x 的位数可以用以 10 为底取对数再向上取整的方法求得,即 digit( x ) = ceil ( log10( x ) );

那么,阶乘的位数可以直接求:digit( n! ) = ∑ log10( i ) ( i 从 1 取到 n ) 

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int t,n;
 6     double ans;
 7     scanf("%d",&t);
 8     while(t--)
 9     {
10         ans = 0;
11         scanf("%d",&n);
12         for(int i = 1; i <= n; i++)
13         {
14             ans += log10(i);
15         }
16         printf("%d
",(int)ans+1);
17     }
18     return 0;
19 }
View Code

另外,在求 n 的阶乘的时候用 Stirling 公式 也是很好的做法,

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const double pi = acos(-1);
 4 int main()
 5 {
 6     int t,n,ans;
 7     scanf("%d",&t);
 8     while(t--)
 9     {
10         scanf("%d",&n);
11         ans = ceil((log(n)*n - n + 0.5*log(2*pi*n) )/ log(10));
12         printf("%d
",ans);
13     }
14     return 0;
15 }
View Code
日后若能有更好的想法,再来完善。 希望看到的大神不吝赐教 orz
原文地址:https://www.cnblogs.com/Taskr212/p/9528359.html