• 杭电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等慢吗? , 然而事实就是这样, 看来,书上说的也未必正确 。 虽然这个道理大家都懂, 但是不知不觉中还是迷信权威。 现实情况是千变万化的, 面对不同的情况会有意料之外的结果。 所以永远不要自以为是,永远不要把话说的太绝对, -------好像陷入悖论啦。 呵呵!

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

  • 相关阅读:
    js获取当前时间
    报错: unable to register MBean
    elasticsearch UNASSIGNED 处理
    esql
    记一次shell脚本编写及执行
    elasticsearch _script 脚本排序
    六大类常用的专业搜索工具
    动态设置所有string字段不分词
    @ResponseBody和@RequestBody使用
    Request method 'POST' not supported
  • 原文地址:https://www.cnblogs.com/acm1314/p/4619207.html
Copyright © 2020-2023  润新知