題目信息
問題描述
輸入一個正整數n,輸出n!的值。
其中n!=123*…*n。
算法描述
n!可能很大,而計算機能表示的整數範圍有限,需要使用高精度計算的方法。使用一個數組A來表示一個大整數a,A[0]表示a的個位,A[1]表示a的十位,依次類推。
將a乘以一個整數k變爲將數組A的每一個元素都乘以k,請注意處理相應的進位。
首先將a設爲1,然後乘2,乘3,當乘到n時,即得到了n!的值。
輸入格式
輸入包含一個正整數n,n<=1000。
輸出格式
輸出n!的準確值。
樣例輸入
10
樣例輸出
3628800
解題思路
主要考察
本題給出的主要考察關鍵字是:高精度
。首先我們要明白什麼是高精度算法:
高精度算法,屬於處理大數字的數學計算方法。在一般的科學計算中,會經常算到小數點後幾百位或者更多,當然也可能是幾千億幾百億的大數字。一般這類數字我們統稱爲高精度數,
高精度算法是用計算機對於超大數據的一種模擬加,減,乘,除,乘方,階乘,開方等運算。
對於非常龐大的數字無法在計算機中正常存儲,於是,將這個數字拆開,拆成一位一位的,或者是四位四位的存儲到一個數組中,用一個數組去表示一個數字
,這樣這個數字就被稱爲是高精度數
。高精度算法就是能處理高精度數各種運算的算法,但又因其特殊性,故從普通數的算法中分離,自成一家。
通過上面的解釋再加上題目提供的算法描述,我們就可以明白如何使用高精度算法來求一個數的階乘了。
解題思路
如果已經明白了後面這段文字可以跳過,直接看代碼,代碼裏也有相應的解釋。計算過程實際上就是在模擬我們算乘法的過程,我們將存大數的數組初始化爲1,然後我們從2開始乘直到相乘到n。比如我們定義存儲的數組爲a[]。我們使a[0]存儲數字的個位,a[1]存儲十位,a[2]存儲百位……依次類推。當我們計算到數字k的時候我們從a[0]開始使數組中的每一個元素乘以k(這也是我們計算乘法的方法),在將每一位乘以k的同時我們要注意進位問題,我們使用一個變量carry來存儲進位並將其初始化爲0。每次的都將(a[i]*k)
+carry
,即該位數乘以k加上上一次的進位數。然後我們再將該結果對10取模,求出當前結果的個位數並將該數存到當前位置,然後再將該數除以10求出當前結果的進位數。不斷的進行循環最終就可以求出結果。
注意:
計算之前一定要將數組的每一位初始化爲0
由於我們是從低位向高位計算存儲的,所以我們輸出的時候應該倒着輸出,即從高位到低位輸出。這裏我們初始化數組的空間爲4000,如果我們直接倒着輸出肯定會先輸出很多很多的0,所以我們需要倒着遍歷一下數組,直到數組元素不爲0爲止,我們將這個數標記爲k,然後輸出時我們直接從k倒着輸出即可
解題代碼
#include<iostream>
using namespace std;
#define MAX 4000
int main(){
int a[MAX] = {0}; //將每一位初始化爲0
int n;
cin>>n;
a[0] = 1; //初始化數組中的數爲 1
//從 2 一直乘到 n
for(int i=2;i<=n;i++){
int carry = 0; //用carry記錄進位
//每次都將當前數組中存儲的數字乘以 i
for(int j=0;j<MAX;j++){
int t = a[j]*i + carry; //將數組中當前的數的每一位乘以j,在加上上一位的進位
a[j] = t%10; //將當前位置乘以 i 的結果保存到j位
carry = t/10; //計算進位,如果超過10,保留的會是十位上的數,不超10 carry 爲 0
}
}
int k; //使用k來標記數組的長度
for(k = MAX-1;k>=0;k--){
if(a[k]){
//在數組中從後往前遍歷,找到第一個不爲0的數,記錄此時數組中k的位置
break;
}
}
//輸出結果,因爲我們是按照從低位到高位計算的,但是我們要按照從高位到低位輸出
for(int i=k;i>=0;i--){
cout<<a[i];
}
return 0;
}
以上就是對於本題的解題思路了。如果你覺得我的文章對你有用請點個贊支持一下吧,喜歡我寫的文章那麼請點個關注再走喲。如果此文章有錯誤或者有不同的見解歡迎評論或者私信。
我是ACfun:一個成長中的程序猿,感謝大家的支持。