hdu 4965 Fast Matrix(矩阵快速幂)

题目链接:点击打开链接


两个矩阵A,B,求(A*B)的N*N次幂。其中元素都%6

因为N范围是1000,K范围是6,如果直接对A*B快速幂的话是对一个1000*1000的矩阵操作,会TLE。所以可以先求出B*A的(N*N-1)次方,这是一个5*5的矩阵,再右乘A左乘B。


快速幂模板还是写vector的比较好

代码:

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

struct mat{
    int n,m;
    vector<vector<int> >a;
    mat(int n,int m):n(n),m(m){
        a.resize(n);
        for(int i=0;i<n;i++){
            a[i].resize(m,0);
        }
    }
    friend mat operator *(const mat &T,const mat &V){
        mat tmp(T.n,V.m);
        for(int i=0;i<T.n;i++){
            for(int j=0;j<T.m;j++){
                for(int k=0;k<V.m;k++){
                    tmp.a[i][k]+=T.a[i][j]*V.a[j][k];
                    tmp.a[i][k]%=6;
                }
            }
        }
        return tmp;
    }
    mat pow(int p){
        mat tmp(n,n);
        mat k(n,n);
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                k.a[i][j]=a[i][j];
            }
        }
        for(int i=0;i<n;i++){
            tmp.a[i][i]=1;
        }
        while(p){
            if(p&1){
                tmp=tmp*k;
            }
            k=k*k;
            p>>=1;
        }
        return tmp;
    }
};

int main(){
    int N,K;
    while(~scanf("%d%d",&N,&K)){
        if(!N&&!K) break;
        mat x(N,K);
        for(int i=0;i<N;i++){
            for(int j=0;j<K;j++){
                scanf("%d",&x.a[i][j]);
            }
        }
        mat y(K,N);
        for(int i=0;i<K;i++){
            for(int j=0;j<N;j++){
                scanf("%d",&y.a[i][j]);
            }
        }
        mat c(K,K);
        c=y*x;
        mat res(N,N);
        res=c.pow(N*N-1);
        res=x*res;
        res=res*y;
        int ans=0;
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                ans+=res.a[i][j];
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值