高精度階乘

高精度階乘其實就是進行了 n 次高精乘以低精,只要高精乘以低精會寫,高精度階乘就沒問題。ios

 

 

那麼先說一說高精乘以低精吧。數組

 

高精乘以低精就是把高精度數的每一位乘以低精度數,而後該位的數就是每一次乘積 mod 10 的餘數,而 / 10 獲得的數做爲進位用的數。(這是在數組中每個元素只存一位的前提下)spa

不過關於進位,有必要說一下。是先進位,在相乘,仍是先相乘,再進位。在高精度加法中是無所謂的,然而在乘法中就必須分出個前後順序了。(頓時感受和線段樹區間修改 lazy 標記有點像,也是考慮運算數序的問題)code

假設先進位再相乘。好比2895 * 64(假設高精度數是2895)那麼先給得數的最後一位進位,進0,而後再5 *64 = 320,留下來0,32記着用做進位,沒毛病。下一位,先進位9 + 32 = 41,再用41 * 64 = 2624,留下來4,262記着用做進位,可是答案是185280,第二位是8,發現錯了,可見這種方法並不能這麼寫。blog

回想一下小學豎式,確實是先把這一位相乘,再加上上一位進的數。string

 

其實這兩種寫法都行,只不過先相乘再進位要有些小運算,沒有先進位再相乘直觀些。這裏就只講一下先進位再相乘吧。io

 

具體的乘法上面已經模擬過了,就再也不贅述。我只是想強調一下,得數的位數問題,由於最終的積有多少位,咱們並不清楚。這就須要動態更新積的位數了。class

理論上是積的位數最多等於乘數的位數之和,然而若是咱們每一次都去數一遍乘數的位數之和,就顯得有些愚笨了。有一個更簡單的方法:假設題中的 n <= 1000,那麼每一次相乘,最多增長4位。這時咱們能夠每一次都讓積的位數增長4位,而後再刪除前導零,這時獲得的位數就是這一次相乘的真實位數了。stream

 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("\n");
28     return 0;
29 }
相關文章
相關標籤/搜索