用矩陣冪運算計算N的階乘

我採用矩陣冪運算的思想,計算了N的階乘。N小於1000都可計算

 

問題描述

  輸入一個正整數n,輸出n!的值。
  其中n!=1*2*3*…*n

輸入格式

  輸入包含一個正整數nn<=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);
}

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章