• hdu 1018 Big Number


    http://acm.hdu.edu.cn/showproblem.php?pid=1018 

    这个题目好像还是在11年暑假看的呢,一直想用那个大整数乘法把N!求出,然后再用一个strlen函数求出位数,可是一直比较懒,都不愿意写,今天看书的时候,发现书上的讲解太牛了,虽然我不是很懂,还是拿来和大家分享一下吧。

    思路1. 这道题可以采用蛮力法,根据定义,直接求解。所谓N!位数,就是lg(N!)+1(不是很懂),根据数学公式: N ! = 1*2*3……N  <==> lg(N!)=lg(2)+lg(3)+……+lg(n);

    所以呢 代码如下

     1 #include<stdio.h>
    2 #include<string.h>
    3 #include<iostream>
    4 #include<math.h>
    5 using namespace std;
    6 int main()
    7 {
    8 int n,t;
    9 long double sum,i; //这里之所以用 long double是因为log10(参数)这个参数默认的是long double型的
    10 cin>>t;
    11 while(t--)
    12 {
    13 sum=0.0;
    14 cin>>n;
    15 for(i=2;i<=n;i++)
    16 {
    17 sum+=log10(i);
    18 //cout<<sum<<endl;
    19 }
    20 printf("%d\n",((int)sum+1));
    21 }
    22 return 0;
    23 }

    思路2. 这类题,如果计算量比较大时,往往需要数学方面的知识,减少计算量,当然这就不属于蛮力法了。本题还可以采用Stirling公式,在n较大时,可以大大减少计算量

    Stirling公式 n!= sqrt(2* pai * n)*(n/e)^n;(由于不会打开方号,所以就用sqrt代表开方的意思了)  所以 lgn!约等于 (lg( 2 * pai ) + lgn) / 2 +n *(lgn-lge)。

    AC代码如下

    // c1 = lg (2 * pai), c2 = lge
    1
    #include<stdio.h>
    2 #include<string.h>
    3 #include<iostream>
    4 #include<math.h>
    5 using namespace std;
    6 int main()
    7 {
    8 long double n,s,c3;
    9 long double c1=0.798179868358,c2=0.434294481903;
    10 int t;
    11 cin>>t;
    12 while(t--)
    13 {
    14 cin>>n;
    15 c3=log10(n);
    16 s=1;
    17 if(n>3)
    18 s=(c3+c1)/2+n*(c3-c2)+1;
    19 printf("%d\n",(int)s);
    20 //cout<<s<<endl;
    21 }
    22 return 0;
    23 }

    思路3.就是用大整数先求出n的阶乘,然后再用一个strlen函数求长度。耗时挺长的,仅供参考

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    #define M 70000000
    char str[M];
    int a[M],b[M],c[M];
    void ca(int n)
    {
    int i;
    int k;
    str[0]='1';
    str[1]='1';
    int len=1;
    for(i=2;i<=n;i++)
    {
    int j=0;
    for( k=len-1;k>=0;k--)
    a[j++]=str[k]-'0';
    int temp=i;
    int g=0;
    while(temp)
    {
    b[g++]=temp%10;
    temp/=10;
    }
    memset(c,0,sizeof(c));
    for(k=0;k<len;k++)
    {
    for(j=0;j<g;j++)
    {
    c[j+k]+=(a[k]*b[j]);
    if(c[j+k]>9)
    {
    c[j+k+1]+=(c[j+k]/10);
    c[j+k]%=10;
    }
    }
    }
    k=len*g;
    while(!c[k]) k--;
    int h=0;
    for(j=k;j>=0;j--)
    {
    str[h++]=(c[j]+'0');
    }
    len=h;

    }
    }
    int main()
    {
    memset(str,0,sizeof(str));
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
    int n,t;
    cin>>t;
    while(t--)
    {
    cin>>n;
    ca(n);
    int len=strlen(str);
    cout<<len<<endl;
    }
    return 0;
    }




  • 相关阅读:
    分组背包(课题选择)
    和为n的俩个数的最大lcm
    合唱队形(悬线法)
    郊区春游(状压dp)
    三角形最大周长
    取余妹子数
    树形dp旅游
    L1-033 出生年
    L1-043 阅览室
    L1-044. 稳赢
  • 原文地址:https://www.cnblogs.com/fxh19911107/p/2381005.html
Copyright © 2020-2023  润新知