矩阵

定义矩阵乘法: C=AB

如果 A mn矩阵, B np矩阵,那么 C 是一个mp矩阵。

其中 Cik=nk=1AijBjk ,如:

[142536]135246=[1+6+154+15+302+8+188+20+36]=[22492864]

矩阵乘法满足结合律,不满足交换律。

单位矩阵 In

In=100010001

矩阵乘法及快速幂:

struct Matrix{
    int m[M][M];
    Matrix(){
        memset(m,0,sizeof(m));
    }
    void Init(){//初始化单位矩阵 
        for(int i=1;i<=n;i++)
            m[i][i]=1;
    }
    Matrix operator *(const Matrix &a)const{
        Matrix res;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(!m[i][j])continue;
                for(int k=1;k<=n;k++)
                    res.m[i][k]+=m[i][j]*a.m[j][k];
            }
        return res;
    }
};
Matrix Pow(Matrix x,int t){
    Matrix res;
    res.Init();
    while(t){
        if(t&1)res=res*x;
        x=x*x;
        t>>=1;
    }
    return res;
}

POJ3070 Fibonacci

Task:

求斐波那契数列第n位取模P的值。(P=10000,n<=1000000000)

Solution:
首先直接循环是O(n)的。

考虑矩阵快速幂:

[f[n]f[n1]]=[1110][f[n1]f[n2]]

[f[n]f[n1]]=[1110]n1[f[1]f[0]]=[1110]n1[10]An1B

于是将这个矩阵 A 快速幂,就可以在O(logn)时间内解决这道题了。

#include<stdio.h>
#include<string.h>
#define M 5
#define P 10000
const int n=2;
struct Matrix{
    int m[M][M];
    Matrix(){
        memset(m,0,sizeof(m));
    }
    void Init(){//初始化单位矩阵 
        for(int i=1;i<=n;i++)
            m[i][i]=1;
    }
    Matrix operator *(const Matrix &a)const{
        Matrix res;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(!m[i][j])continue;
                for(int k=1;k<=n;k++)
                    res.m[i][k]=(res.m[i][k]+m[i][j]*a.m[j][k])%P;
            }
        return res;
    }
};
Matrix Pow(Matrix x,int t){
    Matrix res;
    res.Init();
    while(t){
        if(t&1)res=res*x;
        x=x*x;
        t>>=1;
    }
    return res;
}
int main(){
    Matrix B;
    B.m[1][1]=1;B.m[2][1]=0;
    while(1){
        int d;
        scanf("%d",&d);
        if(d==-1)break;
        if(!d){
            puts("0");
            continue;
        }
        Matrix A;
        A.m[1][1]=A.m[1][2]=A.m[2][1]=1;A.m[2][2]=0;
        A=Pow(A,d-1);
        A=A*B;
        printf("%d\n",A.m[1][1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值