Loading

矩阵快速幂——分治

时间复杂度 O(log n)

高效率计算矩阵的高次方

原理:矩阵乘法的结合律

比如:A*A*A*A*A*A ==> (A*A)*(A*A)*(A*A)

要做到减少重复计算,即充分利用现有的计算结果,考虑使用二分

求A^19次时,使用二进制把问题离散化,转为求(A16)*(A2)*(A)

矩阵快速幂模板 求Ak

#include<iostream>
#include<cstring>
const int mod=1e9+7;
typedef long long ll;
using namespace std;

struct Mat {
    ll m[101][101];
}a,e;
//a是输入的矩阵,e是单位矩阵

ll n,k;

Mat Mul(Mat x,Mat y) { //矩阵乘 返回乘后的矩阵
    Mat ans;
    memset(ans.m,0,sizeof(ans.m));
    for(int i=1; i<=n; i++)
    for(int j=1; j<=n; j++)
    for(int k=1; k<=n; k++)
    ans.m[i][j]=ans.m[i][j]%mod+x.m[i][k]*y.m[k][j]%mod;
    return ans;
}

Mat ksm(Mat x,ll b) {
    Mat ans=e;
    while(b) {
        if(b&1) ans=Mul(ans,x);
        x=Mul(x,x);
        b>>=1;
    }
    return ans;
}

int main( ) {
    cin>>n>>k;
    
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    cin>>a.m[i][j];
    
    for(int i=1;i<=n;i++) e.m[i][i]=1;
    
    Mat ans=ksm(a,k);
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++)
        cout<<ans.m[i][j]%mod<<" ";
        cout<<endl;
    }
    return 0;
}
View Code

例题:https://www.luogu.org/problem/P3390

 

矩阵快速幂求斐波那契

在斐波那契数列中

f[i] = 1*f[i-1] + 1*f[i-2]

f[i-1] = 1*f[i-1] + 0*f[i-2];

用矩阵表示:

或者

对于斐波那契额,构造结构体

代码 

 

#include <iostream>
#include <cstring>
using namespace std;

struct Mat {
    long long A[2][2];
};

Mat Mul(Mat x, Mat y) {
    
    Mat ans;
    memset(ans.A, 0, sizeof(ans.A));

    for(int i = 0; i < 2; i++) {
        for(int j = 0; j < 2; j++) {
            for(int k = 0; k < 2; k++) {
                ans.A[i][j] = ans.A[i][j] + x.A[i][k] * y.A[k][j];
            }
        }
    }

    return ans;
}

void quickpow(int n) {
    
    Mat x,res;

    //x为输入矩阵
    x.A[0][0] = x.A[0][1] = x.A[1][0] = 1;
    x.A[1][1] = 0;

    memset(res.A, 0, sizeof(res.A));

    //单位矩阵
    for(int i = 0; i < 2; i++) res.A[i][i] = 1;

    while(n) {
        if(n & 1) res = Mul(res, x);
        x = Mul(x, x);
        n >>= 1;
    }
    cout << res.A[0][1] << endl;
    
}

int main( ) {
    
    int n;
    while(cin >> n) {
        quickpow(n);
    }
    return 0;
    
}

 

 

 

例题:http://poj.org/problem?id=3070

 

posted @ 2019-03-27 13:03  qinuna  阅读(246)  评论(0编辑  收藏  举报