用矩阵幂运算计算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);
}

 

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