我採用矩陣冪運算的思想,計算了N的階乘。N小於1000都可計算
問題描述
輸入一個正整數n,輸出n!的值。
其中n!=1*2*3*…*n。
輸入格式
輸入包含一個正整數n,n<=1000。
輸出格式
輸出n!的準確值。
樣例輸入
10
樣例輸出
3628800
想法:
- 直接用整數表示,肯定不夠用。32位的int類型好像最多隻能表示到12的階乘
- 乘法即加法,直接套用字符串類型整數相加的函數。這種寫法直接超時
- 優化:採用矩陣冪運算的思想,減少計算次數。AC
#include <bits/stdc++.h>
using namespace std;
//將字符串倒置,方便計算
void traverse(char *str) {
int len = strlen(str);
for (int i = 0; i < len / 2; ++i) {
swap(str[i],str[len-i-1]);
}
}
//單純的兩個大整數相加
void add(char* a, char* b,char* res){
int carry=0;
int len = min(strlen(a),strlen(b));
for (int i = 0; i < len; ++i) {
int s=a[i]-'0'+b[i]-'0'+carry;
carry=s/10;
res[i]=s%10+'0';
}
if(len==strlen(a)) {
int i =len;
while (i<strlen(b)) {
int s;
if(i!=strlen(b)) s=b[i]-'0'+carry;
else s=carry;
carry=s/10;
res[i]=s%10+'0';
i++;
}
if(carry==0) res[i]='\0';
else {
res[i]=carry+'0';
res[i+1]='\0';
}
} else {
int i = len;
while (i<strlen(a)) {
int s;
if(i!=strlen(a)) s=a[i]-'0'+carry;
else s=carry;
carry=s/10;
res[i]=s%10+'0';
i++;
}
if(carry==0) res[i]='\0';
else {
res[i]=carry+'0';
res[i+1]='\0';
}
}
}
int main() {
freopen("../data","r",stdin);
char str[1000005]="1";
char res[1000005]="1";
int N;
scanf("%d",&N);
//如果不考慮超時,可以直接使用下面註釋掉的for循環代替下面的for循環
// for(int i=2; i <= N;i++) {
// strcpy(str,res);
// for (int j = 0; j < i-1; j++) {
// add(str,res,res);
// }
// }
for (int i = 2; i <= N; i++) {
strcpy(str,res);
int M = i-1;
//如下采用了矩陣快速冪的模板算法
while (M) {
if(M&1) {
add(res,str,res);
}
M = M>>1;
add(str,str,str);
}
}
traverse(res);
puts(res);
}