高精度階乘其實就是進行了 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 }