hdoj1042 大数阶乘

Problem D

Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 262144/262144K (Java/Other)

 

Problem Description

Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!

Input

One N in one line, process to the end of file.

Output

For each N, output N! in one line.

Sample Input

1
2
3

Sample Output

1
2
6

这题一开始看起来真的好简单 以至于我飞快写完了然后Time Limit Exceeded 好像是我第一次接触大数?后来去练了大数的加法然后又听老师讲了一遍这个才慢慢理解 真的想了挺久 感觉自己好笨..救命

下面更多的是老师的思路 感觉通过这道题学到了很多 以后还要再多敲一敲关于大数的题目

最后优化完的代码运行出来只有499ms 真的好快啊

题意:

       求N!  ,注意的是N的范围[0,10000],即要考虑程序能够处理“10000!”

思路:
       首先要考虑数据N!的位数,以便于知道声明多大的数组来存储。估算最大值10000!的位数:
       10000! = 10000*9999*9998*...*5*4*3*2*1
       位数= 5 + 9000*4 + 900*3 + 90*2 + 10*1 => 38865
       位数计算的解释:1000~9999共有9000个,每乘一个这样的数会让结果增加约4位,因此为9000*4,其它项式依此类推。
       综上,可以开一个40000的int数组存放,然后用常规法去计算。

优化:

       十万进制:int数组一个元素只存1位数字太浪费了,不如让它的空间发挥到极限,即数组的一个元素存一个不
       超过10^5的数(为什么是这个值,而不是更大或更小的值,见代码中的注释)。改进版是一个元素存5位十进制数,
       位数是前面的1/5,因此开数组大小开为:8000

代码:

#include<iostream>
#define N 8000
int a[N];//定义为全局数组以防栈溢出,但是对于本题来说应该还不需要
int main()
{
    using namespace std;
    int n,i,j,k,t,digit;
    while(cin>>n)
    {
        if(n==0||n==1)
        {
            cout<<1<<endl;
            continue;
        }
        a[0]=1;//真正的大数从位置1开始,起始值为1,然后依次乘以2,3,4,...n
        digit=1;//有效位:初始为1
        for(i=2;i<=n;i++)//分别让2,3,4...n去乘大数s[]
        {
            for(j=0,t=0;j<digit;j++)//计算i乘大数s[]:让i分别乘大数s[]中的每一个元素s[j]
            {
                k=a[j]*i+t;//t为进位   ★★★★★解释为什么本题的“十万进制”是极限。因为:i可以大到10^4,t也可以接近10^4,而k是int类型(不超过10位),由此得出进制的极限值。
                t=k/100000;//★★
                a[j]=k%100000;//★★
            }
           //原有效位数再往前推进,而且可能同时进几位
            while(t)
            {
                a[digit]=t%100000;//★★
                t/=100000;//★★
                digit++;
            }
        }
        cout<<a[digit-1];//第一个元素(最高位位置)不要输出多余的0//★★
        digit-=2;
        while(digit+1)
           printf("%05d",a[digit--]);//第二、三及后面的元素要输出多余的0
        cout<<endl;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值