矩阵快速幂学习入门

来源:互联网 发布:java 发送邮件 maven 编辑:程序博客网 时间:2024/06/06 05:02


矩阵快速幂的原理是跟普通的快速幂一样,不过原来是数与数相乘,而矩阵快速幂是矩阵与矩阵相乘;

矩阵快速幂是运用于处理一些表达式进行多次递归会超时的问题;难点就是怎样构造矩阵,比如f[ n ] = f[n - 1] + f[ n - 2],

那么构造成的矩阵为:

1 1 

1 0;

模板:

typedef struct{    ll a[7][7];    void Init()    {        memset(a,0,sizeof(0));        for(int i = 1; i < 7; i ++)        {            a[i][i] = 1;        }    }}Matrix;Matrix p ={    1,2,1,4,6,4,1,    1,0,0,0,0,0,0,    0,0,1,4,6,4,1,    0,0,0,1,3,3,1,    0,0,0,0,1,2,1,    0,0,0,0,0,1,1,    0,0,0,0,0,0,1};Matrix Matrix_Mul(Matrix a,Matrix b){    Matrix c;    for(int i = 0; i < 7; i ++)    {        for(int j = 0; j < 7; j ++)        {            c.a[i][j] = 0;            for(int k = 0; k < 7; k ++)            {                c.a[i][j] += (a.a[i][k] * b.a[k][j]) % MOD;                c.a[i][j] %= MOD;            }        }    }    return c;}Matrix pow_Matrix(ll m){    Matrix ans,b = p;    memset(ans.a,0,sizeof(ans.a));    for(int i = 0; i < 7; i ++)    {        ans.a[i][i] = 1;    }    while(m)    {        if(m & 1)        {            ans = Matrix_Mul(ans,b);        }        m >>= 1;        b = Matrix_Mul(b,b);    }    return ans;}


hdu2157


这是裸的矩阵快速幂,给出的图就是要进行相乘的矩阵,

代码:

#include <stdio.h>#include <string.h>#include <algorithm>#include<bits/stdc++.h>typedef long long ll;using namespace std;typedef long long ll;const int maxn = 100 + 10;#define mod 1000struct Matrix{    ll a[maxn][maxn];}origin,res;void Init(ll n){    memset(res.a,0,sizeof(res.a));    for(ll i = 0; i < n ; i ++)    {        res.a[i][i] = 1;    }}Matrix Matrix_multi(Matrix aa,Matrix bb,ll n)//两矩阵相乘的算法{    Matrix ress;    memset(ress.a,0,sizeof(ress));    for(ll i = 0; i < n ; i ++)    {        for(ll  j = 0; j < n ; j ++)        {            for(ll k = 0; k < n ; k ++)            {                ress.a[i][j] += aa.a[i][k] * bb.a[k][j];            }        }    }    return ress;}void Matrix_calc(ll n,ll k)//矩阵快速幂{    Matrix origins = origin;    while(k)    {        if(k & 1)        {            res = Matrix_multi(res,origins,n);        }        origins = Matrix_multi(origins,origins,n);        k >>= 1;    }}int main(){    int n,m;    while( ~ scanf("%d%d",&n,&m) && (n || m) )    {        Init(n);        memset(origin.a,0,sizeof(origin.a));        for(ll i = 1; i <= m ; i ++)        {            int x,y;            scanf("%d%d",&x,&y);            origin.a[x][y] = 1;        }        int q;        scanf("%d",&q);        for(ll i = 1; i <= q; i ++)        {            Init(n);            int x,y,k;            scanf("%d%d%d",&x,&y,&k);            Matrix_calc(n,k);            cout << res.a[x][y] % mod <<endl;        }    }    return 0;}

hdu5950   Recursive sequence


题意:f[ n ] = f[n - 1] + 2 * f[n - 2] + n * 4;  n的范围< 2^31;

思路:数据范围很大,

首先一看这个题目,很容易想到构造矩阵:那么我们现在来分析一下怎么构造这个矩阵,那么 (n+1)^4 = n^4+4n^3+6n^2+4^n+1 所以光 (n+1)^4 这个矩阵就能构造出 5∗5 的一个矩阵来, 然后 f(n) = f(n−1)+2∗f(n−2) 这个是 2∗2 的矩阵,所以构造出来就应该是 7∗7 的转移矩阵 A : 
{f(n),f(n−1),n^4,n^3,n^2,n,1}∗A={f(n+1),f(n),(n+1)^4,(n+1)^3,(n+1)^2,(n+1),1}
然后 f(n+1) = f(n)+2∗f(n−1)+(n+1)4, 可得矩阵 A: 

Matrix p =
{
    1,2,1,4,6,4,1,
    1,0,0,0,0,0,0,
    0,0,1,4,6,4,1,
    0,0,0,1,3,3,1,
    0,0,0,0,1,2,1,
    0,0,0,0,0,1,1,
    0,0,0,0,0,0,1
};

然后就是直接代码了:

#include<bits/stdc++.h>using namespace std;typedef long long ll;#define MOD 2147493647const int maxn = 200+ 20;typedef struct{    ll a[7][7];    void Init()    {        memset(a,0,sizeof(0));        for(int i = 1; i < 7; i ++)        {            a[i][i] = 1;        }    }}Matrix;Matrix p ={    1,2,1,4,6,4,1,    1,0,0,0,0,0,0,    0,0,1,4,6,4,1,    0,0,0,1,3,3,1,    0,0,0,0,1,2,1,    0,0,0,0,0,1,1,    0,0,0,0,0,0,1};Matrix Matrix_Mul(Matrix a,Matrix b){    Matrix c;    for(int i = 0; i < 7; i ++)    {        for(int j = 0; j < 7; j ++)        {            c.a[i][j] = 0;            for(int k = 0; k < 7; k ++)            {                c.a[i][j] += (a.a[i][k] * b.a[k][j]) % MOD;                c.a[i][j] %= MOD;            }        }    }    return c;}Matrix pow_Matrix(ll m){    Matrix ans,b = p;    memset(ans.a,0,sizeof(ans.a));    for(int i = 0; i < 7; i ++)    {        ans.a[i][i] = 1;    }    while(m)    {        if(m & 1)        {            ans = Matrix_Mul(ans,b);        }        m >>= 1;        b = Matrix_Mul(b,b);    }    return ans;}int main(){    int Tcase;    scanf("%d",&Tcase);    for(int ii = 1; ii <= Tcase; ii ++)    {        ll n,a,b;        scanf("%I64d%I64d%I64d",&n,&a,&b);        if(n == 1)        {            cout << a << endl;            continue;        }        if(n == 2)        {            cout << b << endl;            continue;        }        Matrix ans = pow_Matrix(n - 2);        ll anss = 0;        anss = (anss +  ans.a[0][0] * b % MOD) % MOD;        anss = (anss +  ans.a[0][1] * a % MOD) % MOD;        anss = (anss +  ans.a[0][2] * 16 % MOD) % MOD;        anss = (anss +  ans.a[0][3] * 8 % MOD) % MOD;        anss = (anss +  ans.a[0][4] * 4 % MOD) % MOD;        anss = (anss +  ans.a[0][5] * 2 % MOD) % MOD;        anss = (anss +  ans.a[0][6] * 1 % MOD) % MOD;        cout << anss << endl;    }    return 0;}






0 0
原创粉丝点击