矩阵快速幂

类似于快速幂
矩阵快速幂是一个Matrix 的k次方
\(|A|^{k}=|A|^{k/2}*|A|^{k/2}\)
对于这种幂的(自己乘以自己,可以用快速幂来求)

对于任何线性递归式,都可以进行矩阵加速
可以吧O(n)的线性进行转换为O(\(log_{2}n * C\))C 是常数,有题目决定

快速幂

Matrix ksm(Matrix a,int b){
    if(b == 0)return a;
    Matrix ans(a.n,a.m);
    int maxx = max(a.n,a.m);
    for(int i = 0; i <= maxx; i++)ans.a[i][i] = 1;
    while(b){
        if(b & 1)ans = ans * a;
        a = a * a;
        b >>= 1;
    }
    return a

矩阵相乘

Matrix operator * (const Matrix &a,const Matrix &b){
    Matrix ans(a.n,b.m);
    for(int i = 0; i < a.n; i++){
        for(int j = 0; j < b.m; j++){
            for(int k = 0; k < a.m; k++){
                ans.a[i][j] = (ans.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
            }
        }
    }
    return ans;
}

矩阵的定义

struct Matrix{
	int n,m;
	int a[N][N];
	Matrix(int x,int y):n(x),m(y){memset(a,0,sizeof(a));}
};

也可以在矩阵定义中重载

struct Matrix{
    int n,m;
    int a[11][11];
    Matrix(int x,int y):n(x),m(y){memset(a,0,sizeof(a));}
    Matrix operator * (const Matrix &b){
        Matrix ans(n,b.m);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < b.m; j++){
                for(int k = 0; k < m; k++){
                    ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
                }
            }
        }
        return ans;
    }
};

矩阵快速幂

#include <iostream>
#include <cstdio>
#include <algorithm>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define mod 1000000007
#define ll long long
using namespace std;
const int N = 25;
struct Matrix{
    int n,m;
    int a[11][11];
    Matrix(int x,int y):n(x),m(y){memset(a,0,sizeof(a));}
    Matrix operator * (const Matrix &b){
        Matrix ans(n,b.m);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < b.m; j++){
                for(int k = 0; k < m; k++){
                    ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
                }
            }
        }
        return ans;
    }
};
Matrix ksm(Matrix a,int b){
    if(b == 0)return a;
    Matrix ans(a.n,a.m);
    int maxx = max(a.n,a.m);
    for(int i = 0; i <= maxx; i++)ans.a[i][i] = 1;
    while(b){
        if(b & 1)ans = ans * a;
        a = a * a;
        b >>= 1;
    }
    return ans;
}
int main(){
    
    return 0;
}

矩阵快速幂进行加速

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 15;
int k,mod;
int a[maxn];
struct Matrix{
    int n,m;
    int a[11][11];
    Matrix(int x,int y):n(x),m(y){memset(a,0,sizeof(a));}
    Matrix operator * (const Matrix &b){
        Matrix ans(n,b.m);
        for(int i = 0; i < n; i++){
            for(int j = 0; j < b.m; j++){
                for(int k = 0; k < m; k++){
                    ans.a[i][j] = (ans.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
                }
            }
        }
        return ans;
    }
};
Matrix ksm(Matrix a,int b){
    if(b == 0)return a;
    Matrix ans(a.n,a.m);
    int maxx = max(a.n,a.m);
    for(int i = 0; i <= maxx; i++)ans.a[i][i] = 1;
    while(b){
        if(b & 1)ans = ans * a;
        a = a * a;
        b >>= 1;
    }
    return ans;
}
Matrix x(10,10);
int getans(int k){
    if(k < 10)return k;
    Matrix y(10,10);
    y = ksm(x,k - 9);
    int ans = 0;
    for(int i = 0; i < 10; i++){
        ans = (ans + (9 - i) * y.a[0][i] % mod) % mod;
    }

    return ans;
}
int main(){
    while(cin >> k >> mod){
        for(int i = 0; i < 10; i++){
            scanf("%d",&x.a[0][i]);
        }
        for(int i = 1; i < 10; i++){
            x.a[i][i - 1] = 1;
        }
        cout << getans(k) << endl;
    }
    return 0;
}
posted @ 2019-10-24 18:46  Emcikem  阅读(241)  评论(0编辑  收藏  举报