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

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

时间: 2024-08-24 03:35:51

杭电HDU1042(有点坑的高精度)的相关文章

hdu1702(ACboy needs your help again!) 在杭电又遇坑了

点击打开链接 结题感悟: 其实吧,这题并不是很难,就是一个栈和队列的公共题,也就是按指定的方式(栈或队列)存取数据,但是为什么我自己写的栈和队列就是不能再杭电ac(一直wa啊),而用java包中的栈和队列就秒过了,问题尚未找出原因,值得思考啊.不过可以趁此学学这两个类(尽量还是自己动手写的好啊) 栈:java.util 类 Stack<E> Stack 类表示后进先出(LIFO)的对象堆栈.它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈.它提供了通常的push 和 pop

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY

杭电1272 并查集找环+判断连通

杭电1272 并查集找环+判断连通 E - E Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1272 Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B

【转】对于杭电OJ题目的分类

[好像博客园不能直接转载,所以我复制过来了..] 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDI

杭电1272~~小希的迷宫——并查集判断是否存在环

今天,刚学习了并查集对于并查集,也有了一定的理解了. 杭电1272这一题,主要是给你几对数,表示这两个数(可以理解为村落)直接有路,而从每一个村落到另外一个村落只能有一条路,也就是不能存在环.而并查集就是将有一定联系的村落组成一个部落(也就是集合),如果给的两个村落都存在于同一个部落,也就是存在环了. 还有一种情况就是存在两个部落,也就是有些村落到不了另一些村落.这一点,我们需要通过判断 顶点数减掉边数 是否等于,如果是,那就符合,不是,那就不符合. 也就是下面的情况: 这一题还有一个很坑的地方

杭电 1272 POJ 1308 小希的迷宫

这道题是我学了并查集过后做的第三个题,教我们的学姐说这是并查集的基础题,所以有必要牢牢掌握. 下面就我做这道题的经验,给大家一些建议吧!当然,我的建议不是最好的,还请各位大神指出我的错误来,我也好改正. 1.题目概览 这道题是杭电1272,POJ 1308如果写好了代码可以试一试. 小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s

杭电2549(第一次用java写kmp算法)

点击打开杭电2549 Problem Description Homer: Marge, I just figured out a way to discover some of the talents we weren't aware we had. Marge: Yeah, what is it? Homer: Take me for example. I want to find out if I have a talent in politics, OK? Marge: OK. Home

杭电 1408 盐水的故事(double精度问题)

盐水的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13446    Accepted Submission(s): 3272 Problem Description 挂盐水的时候,如果滴起来有规律,先是滴一滴,停一下:然后滴二滴,停一下:再滴三滴,停一下...,现在有一个问题:这瓶盐水一共有VUL毫升,每一滴是D毫升,每一滴的

求平均成绩 【杭电-HDOJ-2023】 附题+详解

/* 求平均成绩 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 62086    Accepted Submission(s): 14888 Problem Description 假设一个班有n(n<=50)个学生,每人考m(m<=5)门课,求每个学生的平均成绩和每门课的平均成绩,并输出各科成绩均大于等于平均成绩的学生数量. In