zoukankan      html  css  js  c++  java
  • 杭电HDU1042(有点坑的高精度)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1042

    题意:

    Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!
    是不是很简单呢?
    一般方法:
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int MAXN = 10000;
    int a[MAXN];
    
    int main()
    {
        int N, k, temp;
        while(scanf("%d", &N)!=EOF)
        {
            memset(a, 0, sizeof(a));
            a[0]=1; 
            for(int i=1; i<=N; i++)
            {
                k=0;
                for(int j=0; j<MAXN; j++)
                {
                    a[j]=a[j]*i+k;
                    k=a[j]/10;
                    a[j]%=10;
                }
            }
            int t;
            for(t=MAXN-1; t>=0; t--)
            if(a[t])
            {
                //cout<<t<<endl;
                break;
            }    
            for(int i=t; i>=0; i--)
            printf("%d", a[i]);
            printf("
    ");
        }
        return 0;
    }

    上面的代码是不是和你的想法相同呢?, 很遗憾, 上述代码一定会超时! 那么 , 能不能把数组开小些呢? ----> 不能。 当N=10000时, 你会发现数组要开到9999。很明显, 这道题就是要卡你的时间, 就是要卡你的优化。 下面是两个优化思路:

    1. 合并计算:  从而减少计算次数, 例如 你在每个a[i]中存10000数量级的数, 然后这个数组的长度就成2000啦! 但是这种算法在实现时要考虑很多情况, 比较繁琐!

    2.过程优化: 由于结果值在计算时, 数位变化很大, 但是上述代码, 在计算时每次都按MAXN-1 位计算, 所以做了很多的无用功。如果每次计算时都顺带着算出位数, 这样就可以节省很多时间。代码只需稍加改动即可!

    3.综合使用前两种方法!

    由于第一和第三中方法较繁琐, 我不再理会!

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    const int MAXN=100002;
    int a[MAXN];
    
    int main()
    {
        int N;
        int k,count,temp;
        while(scanf("%d", &N)!=EOF)
        {
            a[0]=1;
            count=1;
            for(int i=1;i<=N;i++)
            {
                k=0;
                for(int j=0;j<count;j++)
                {
                    temp=a[j]*i+k;
                    a[j]=temp%10;
                    k=temp/10;    
                }
                while(k)//¼Ç¼½øÎ»    
                 {
                    a[count++]=k%10;
                    k/=10;
                }
            }
                for(int i=count-1;i>=0;i--)
                    printf("%d", a[i]);
                    printf("
    ");
        }
        return 0;
    }

    耗时: 1045MS  时限是5s。

    然而:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    const int MAXN = 100000;
    int main()
    {
        int n, a[MAXN];
        int i, j, k, count, temp;
        while(cin>>n)
        {
            a[0]=1;
            count=1;
            for(i=1; i<=n; i++)
            {
                k=0;
                for(j=0; j<=count; j++)
                {
                    temp=a[j]*i+k;
                    a[j]=temp%10;
                    k=temp/10;
                }
                while(k)
                {
                    a[count++]=k%10;
                    k/=10;
                }
            }
            for(j=MAXN-1; j>=0; j--)
            if(a[j])
            break;
            for(i=count-1; i>=0; i--)
            cout<<a[i];
            cout<<endl;
        }
        return 0;
    }

    耗时: 811MS    很是令人费解! cin和cout不应该比scanf等慢吗? , 然而事实就是这样, 看来,书上说的也未必正确 。 虽然这个道理大家都懂, 但是不知不觉中还是迷信权威。 现实情况是千变万化的, 面对不同的情况会有意料之外的结果。 所以永远不要自以为是,永远不要把话说的太绝对, -------好像陷入悖论啦。 呵呵!

    ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/acm1314/p/4619207.html
Copyright © 2011-2022 走看看