• 高精度阶乘


    高精度阶乘其实就是进行了 n 次高精乘以低精,只要高精乘以低精会写,高精度阶乘就没问题。

    那么先说一说高精乘以低精吧。

    高精乘以低精就是把高精度数的每一位乘以低精度数,然后该位的数就是每一次乘积 mod 10 的余数,而 / 10 得到的数作为进位用的数。(这是在数组中每一个元素只存一位的前提下)

    不过关于进位,有必要说一下。是先进位,在相乘,还是先相乘,再进位。在高精度加法中是无所谓的,然而在乘法中就必须分出个先后顺序了。(顿时感觉和线段树区间修改 lazy 标记有点像,也是考虑运算数序的问题)

    假设先进位再相乘。比如2895 * 64(假设高精度数是2895)那么先给得数的最后一位进位,进0,然后再5 *64 = 320,留下来0,32记着用作进位,没毛病。下一位,先进位9 + 32 = 41,再用41 * 64 = 2624,留下来4,262记着用作进位,但是答案是185280,第二位是8,发现错了,可见这种方法并不能这么写。

    回想一下小学竖式,确实是先把这一位相乘,再加上上一位进的数。

    其实这两种写法都行,只不过先相乘再进位要有些小运算,没有先进位再相乘直观些。这里就只讲一下先进位再相乘吧。

    具体的乘法上面已经模拟过了,就不再赘述。我只是想强调一下,得数的位数问题,因为最终的积有多少位,我们并不清楚。这就需要动态更新积的位数了。

    理论上是积的位数最多等于乘数的位数之和,然而如果我们每一次都去数一遍乘数的位数之和,就显得有些愚笨了。有一个更简单的方法:假设题中的 n <= 1000,那么每一次相乘,最多增加4位。这时我们可以每一次都让积的位数增加4位,然后再删除前导零,这时得到的位数就是这一次相乘的真实位数了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn = 1e5 +5;        //打表可知,开这么大时,n 最多能达到26439
     7 int a[maxn], n, len = 0;   
     8 int main()
     9 {
    10     scanf("%d", &n);
    11     a[0] = 1;
    12     for(int i = 2; i <= n; ++i)            
    13     {
    14         int jinwei = 0;
    15         for(int j = 0; j <= len + 4; ++j)        //假设每一次位数都增加4 
    16         {
    17             a[j] = a[j] *i + jinwei;        //先将这一位相乘,在进位 
    18             jinwei = a[j] / 10;
    19             a[j] %= 10;
    20         }
    21         int x = len + 4;
    22         while(x > 0 && a[x] == 0) x--;        //删除前导零 
    23         len = x;                //得到了真正的位数 
    24     }
    25     while(a[len] == 0 && len > 0)  len--;    //最后再删除一遍前导零 
    26     for(int i = len; i >= 0; --i) printf("%d", a[i]);
    27     printf("
    ");
    28     return 0;
    29 }
  • 相关阅读:
    模板笔记2
    模板笔记
    qt打包可执行文件
    合并单独的视频和音频
    模板1
    mysql 数据表中查找重复记录
    mysql左连接右连接(查询两张表不同的数据)
    mysql--构造数据、导入导出
    mysql安装
    linux下启动tomcat服务
  • 原文地址:https://www.cnblogs.com/mrclr/p/8525701.html
Copyright © 2020-2023  润新知