N!(大数阶乘)

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

一万的阶乘,想想就恐怖,当然longlong也不够折腾的,在网上查了半天,看到一个靠谱的回答,非常感谢博主,把链接贴出来了(https://blog.csdn.net/lisp1995/article/details/52403507)
我就是在这里学的,也是看了好久才看明白,能大概知道其中一些关键步骤的巧妙,在这里做个梳理吧,这题思路大概是模拟人手算乘法的步骤,用数组每一个元素代表一个位,a[0]就是个位a[1]就是十位以此类推,比较巧妙的是如何处理进位这类的运算。首先开一个数组来盛纳阶乘的结果,每个特定元素代表阶乘特定位数上的数字(0-9),初始化a[0]=1,位数l=1,位数比较巧妙(坑1),后续再说,
之后开搞!!
(1)用一个循环遍历2–n之间所有阶乘需要乘的数字。
(2)这一步是对于一个特定的数字(0–n之间的)我们该如何处理,也就是说如何让它模拟手算的步骤。初始化num=0,后续在讨论num的巧妙(坑2),现在经过第一步,我们面前已经摆上了一个需要乘的数字,也就是i,我们如何模拟乘法进位呢?答案就是让我们手上已经获得的数组,也就是这个数i之前的阶乘,让这个数组中的每一位都乘上这个数字i,想想乘法是不是这个道理,可能你会想手算乘法的话每次只用乘一个数啊,怎么会用位数上的数字去直接乘那个数的所有位?这句话好像太绕了,用图来帮助理解一下在这里插入图片描述
比如正常的11阶乘结果39916800乘12,本应该82进位然后62进位类推,而我们现在讨论的方法是812进位然后612进位,其实没什么大区别,只不过你绕不过那个弯,一位一位乘跟直接乘,只要进位得当(num的巧妙哟),也是能得到正确答案的,不多唠叨了,继续进行。我们用一个循环依靠j和位数l的限制关系来遍历所有位数,用t代表每一位上的数字(0–9)乘上i的结果,同时还要加上num(第一次的话初始化为0),乘出的可能很多位,就比如上图的9*12=108,怎么合理进位呢?个位能留的当然用t%10,之后的都是要分别进位的,但不至于单独弄,在j++到下一位时直接加上就好(填了坑2),所以t=a[j]*i+num;这里在循环结束时等于说每一位都乘过了i,但最高位乘i之后还没有进行进位(因为t=a[j]*i+num嘛,j都超了肯定没法进位了)所以我们再用一个循环来处理剩下的进位,也就是
while(num)
{
a[l]=num%10;
num/=10;
l++;
}
这里l就拓宽上界也合适的处理了进位的问题。
之后就是输出了,没什么好说的,下面看完整代码吧!

#include <iostream>
#include<cstring>
#include<cmath>
using namespace std;
int main()
{
    int n;
    while(cin>>n)
    {
       int a[45007]={0},i,l,t,num;//t每次的运算数
       a[0]=1;
       l=1;//l是位数
       for(i=2;i<=n;i++)//i遍历阶乘的所有数
       {
           num=0;
           for(int j=0;j<l;j++)//控制每一次乘的运算每次都从a[0]开始
           {
               t=a[j]*i+num;
               a[j]=t%10;
               num=t/10;
           }
           while(num)
           {
               a[l]=num%10;
               num/=10;
               l++;
           }

       }
       for(i=l-1;i>=0;i--)
           cout<<a[i];
       cout<<endl;
    }
    return 0;
}

感谢观看!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值