51nod1113-----矩阵快速幂

我们先看下矩阵的乘法

51nod1137矩阵乘法 链接51nod1137矩阵乘法

就是模拟人工手算矩阵乘法

这里用了下运算符重载  看起来简洁些  也可以不用

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=110;
typedef struct {
    int Mat[maxn][maxn];
}mat;
int n;
mat operator * (mat a,mat b){
    mat c;
    int sum;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            sum=0;
            for(int k=0;k<n;k++){
                sum+=a.Mat[i][k]*b.Mat[k][j];
            }
            c.Mat[i][j]=sum;
        }
    }
    return c;
}
int main(){
    scanf("%d",&n);
    mat a,b;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            scanf("%d",&a.Mat[i][j]);
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            scanf("%d",&b.Mat[i][j]);
        }
    }
    mat c=a*b;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            printf("%d ",c.Mat[i][j]);
        }
        printf("\n");
    }
    return 0;
}

然后是矩阵快速幂

题目链接51nod1113

先看下普通的快速幂  原理就不再说了  他用来优化求x的n次方的问题

ll pow_mod(ll x,ll n){
    ll res=1;
    while(n){
        if(n&1)
        res=res*x;
        x=x*x;
        n>>=1;
    }
    return res;
}

那么求矩阵的n次方  我们也可以把矩阵看成两个数字  所以 这个运算也可以使用同样的方法去优化

在普通快速幂中 我们的 res初始化为1   而矩阵快速幂 相乘的是矩阵  所以 我们初始化为 单位矩阵(对角线为1)

void init_unit(){
    for(int i=0;i<maxn;i++){
        unit.m[i][i]=1;
    }
    return ;
}

然后剩下的就是套用快速幂的方法  都一样  注意要模mod  我这里是在运算符重载里面取了模了

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=110;
const int mod=1e9+7;
typedef struct mat{
    ll m[maxn][maxn];
};
mat unit;
int n;
ll m;
void init_unit(){
    for(int i=0;i<maxn;i++){
        unit.m[i][i]=1;
    }
    return ;
}
mat operator * (mat a,mat b){
    ll x;
    mat c;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            x=0;
            for(int k=0;k<n;k++){
                x+=(a.m[i][k]*b.m[k][j])%mod;
            }
            c.m[i][j]=x%mod;
        }
    }
    return c;
}
mat pow_mat(mat a,ll n){
    mat ret=unit;
    while(n){
        if(n&1) ret=ret*a;
        a=a*a;
        n>>=1;
    }
    return ret;
}
int main(){
    init_unit();
    scanf("%d%lld",&n,&m);
    mat a;
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    scanf("%lld",&a.m[i][j]);
    mat ans=pow_mat(a,m);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            printf("%I64d ",ans.m[i][j]);
        }
        printf("\n");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1900_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值