zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    ES6入门之Promise对象
    Iterator和ListIterator区别
    try_catch_return
    T-SQL查询进阶--详解公用表表达式(CTE)
    Node.js安装及环境配置之Windows篇
    Java中Lambda表达式的使用
    windows下redis 开机自启动
    IDEA快捷键(修改成eclipse版)+Templates
    oracle赋予一个用户具有查询另一个用户所有表数据
    sql触发器
  • 原文地址:https://www.cnblogs.com/Taskr212/p/9528359.html
Copyright © 2011-2022 走看看