求N的阶乘

1105: 求N的阶乘

时间限制: 3 Sec   内存限制: 65536 MB
提交: 11   解决: 3
[ 提交][ 状态][ 讨论版]

题目描述

我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,我们该如何去计算它并输出它?

输入

输入文件第一行有一个整数n1n50),以下n行每行有个整数k(0<k<5000)。

输出

输出文件有n行,各包含一个结果。

样例输入

2
5
50

样例输出

120
30414093201713378043612608166064768844377641568960512000000000000

提示

解题思路:肯定不能按不同的方法求解;

这是一个大数问题:
我们模拟下乘法运算:

例:192*9;

2*9=18;把8留在个位,1向前进位
9*9=81;把1留在十位,8向前进位
1*9=9;把9留在百位
一个数m与个位数n相乘,是不是把每个m的位数值乘与n所得数值的个位留在当前位,十位进位。

例:51*50;
1*50=50;把0留在个位,5向前进位
5*50=250;把0留在十位,5向前进位,2向前进两位
一个数m与一个数n相乘,是不是把每个m的位数值乘与n所得数值的个位留在当前位,十位进位,百位进两位.....。

明白这些就能解决这个问题。
我们利用数组【0】代表个位,【1】代表十位,【2】代表百位......。


原代码:

#include<cstdio>
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,k=0;
        int num[1005]={0};
        num[0]=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=k;j++)
            {
                num[j]=num[j]*i;
            }
            for(int j=0;j<=k;j++)
            {
                if(num[j]>=100)
                {
                    num[j+2]+=num[j]/100;
                    num[j+1]+=(num[j]-num[j]/100*100)/10;
                    num[j]=num[j]%10;
                }
                if(num[j]>=10)
                {
                    num[j+1]+=num[j]/10;
                    num[j]=num[j]%10;
                }
            }
            if(num[k+2]!=0) k=k+2;
            else if(num[k+1]!=0) k++;
        }
        for(int i=k+1;i>=0;i--)
            printf("%d",num[i]);
        printf("\n");
    }
    return 0;
}


下边是优化过的代码可以解决任意为的阶乘(上边的代码只能解决到100以下的阶乘):

源代码:


#include<cstdio>
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,k=0;
        int num[100005]={0};
        num[0]=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=k;j++)
            {
                num[j]=num[j]*i;
            }
            int l=0;//两个功能,测量增加位数,和进位
            for(int j=0;j<=k;j++)
            {
                if(num[j]>=10)
                {
                    int s=num[j];
                    num[j]=0;
                    l=j;//进位
                    while(s)
                    {
                        num[l++]+=s%10;
                        s=s/10;
                    }
                }
            }
            while(l--)//增加位数
            {
                if(num[k+l]!=0)
                {
                    k=k+l;
                    break;
                }
            }
        }
        for(int i=k;i>=0;i--)
            printf("%d",num[i]);
        printf("\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值