zoukankan      html  css  js  c++  java
  • 求 n! (大数问题)----------HDOJ1042

    以下只YY算法,c++实现,java大神绕道。。。。。

    (1)位数的估计

        显然对于大数(比如1000的阶乘)的阶乘我们找不到一个数据类型存放这个数,是在太大啦。。。。

        那么现在来估计一下这个数的位数:

     

        估计数n的位数的方法:log10(n)+1;

        那么log10(n!)+1=log10(1)+log10(2)+...log10(n)+1,这在计算机中是很容易解决的;

        ps:斯特林公式:n! approx sqrt{2pi n}\, left(frac{n}{e}
ight)^{n}.也可以用它两边取对数求得;

        斯特林公式推导

        

    #include<cstdio>
    #include<cmath>
    int main()
    {
        int n,i;
        double d;
        while(scanf("%d",&n)!=EOF)
        {
            d=0;
            for(i=1; i<=n; i++)
                d+=log10(i);
            printf("%d
    ",(int) d+1);
        }
        return 0;
    }

    (2)求解n!的大小

         看一个例子1567*12=18804:

       我们把前一个数分开为15、67,67*12=804、15*12=180,有下列狮子:

                 15      67

       *                 12

    -----------------------------

                 8       04

        1       80

    -----------------------------

        1       88       04


    那么,计算n的阶乘的时候,n-1的阶乘肯定是很大的,(n-1)!*n就恰好是一个大数乘以一个小的数字;

    比如我们计算0到1000的阶乘,那么计算1000!的阶乘有2568位,这个数就决定数组的要开的大小,开打啦会超时,开小啦不够,我们用一个数组存放阶乘,每一个数组单元存放4位,就可以计算出来啦,详情见代码中的注释吧!

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #define maxs 10000
    //数组的设置的大小,不能开太大,这样的话扫描的时间太长会超时,也不能太小。。。。
    using namespace std;
    int a[maxs];
    int main()
    {
        int n,i,j,y;
        while(scanf("%d",&n)!=EOF)
            {
               memset(a,0,sizeof(a));//把数组全部设置为0
               for(i=1,a[maxs-1]=1;i<=n;i++)//数组的高位存放数的低位,把最低位置成1,从1乘到n
                {
                    y=0;//余数
                    for(j=maxs-1;j>=0;j--)
                        {
                          a[j]=a[j]*i+y;
                          y=a[j]/10000;//得到乘法之后的结果
                          a[j]=a[j]%10000;//得到进位
                        }
                }
                for(i=0;i<maxs;i++)//从左到右扫描,第一个不是0的跳出
                   if(a[i])break;
                printf("%d",a[i++]);//输出第一个不是0的
                for(j=i;j<maxs;j++)
                    printf("%04d",a[j]);//注意中间的数字,比如12,由于在数的中间要输出0012
                printf("
    ");
            }
      return 0;
    }
    
    


  • 相关阅读:
    git
    switch切换
    js object 常用方法总结
    pod install速度慢的终极解决方案
    MacBook Pro 初体验
    LINQ以及LINQ to Object 和LINQ to Entities
    WebService/WCF/WebAPI 之间的区别
    owin
    回车和刷新以及Ctr+F5的区别
    ASP.NET Core 启动流程图
  • 原文地址:https://www.cnblogs.com/riskyer/p/3266610.html
Copyright © 2011-2022 走看看