码迷,mamicode.com
首页 > 其他好文 > 详细

杭电HDU1042(有点坑的高精度)

时间:2015-07-03 17:24:09      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

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

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

杭电HDU1042(有点坑的高精度)

标签:

原文地址:http://www.cnblogs.com/acm1314/p/4619207.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!