Fast Matrix Calculation HDU-4965 矩阵快速幂

Fast Matrix Calculation

在这里插入图片描述

SOLUTION

已 知 A n ∗ k , B k ∗ n , n < 1000 , k < 6 , 要 求 ( A B ) n 2 有 , 已知A_{n*k},B_{k*n},n<1000,k<6,要求(AB)^{n^2}有, AnkBknn<1000k<6(AB)n2,

( A B ) n 2 = A ∗ ( B A ) n 2 − 1 ∗ B , 其 中 ( B A ) k ∗ k (AB)^{n^2}=A*(BA)^{n^2-1}*B,其中(BA)_{k*k} (AB)n2=A(BA)n21B(BA)kk

CODE

/*SiberianSquirrel*/
/*CuteKiloFish*/
#include<bits/stdc++.h>
using namespace std;

const int MOD = 6;

int n, k;
int A[1001][1001], B[1001][1001];
int temp[1001][1001], ans[1001][1001];

struct Matrix {
    static const int M = 6;
    int mx[M][M];
    Matrix(){
        memset(mx, 0, sizeof mx);
    }
    void Out() {
        for(auto & i : mx) {
            for(auto j : i)
                cout << j << ' ';
            cout << endl;
        }
    }
    void Tranfer_E() {
        memset(mx, 0, sizeof mx);
        for(int i = 0; i < M; ++ i) mx[i][i] = 1;
    }
    Matrix operator * (const struct Matrix a)const {
        Matrix x;
        memset(x.mx, 0, sizeof x.mx);
        for(int i = 0; i < M; ++i)
            for(int j = 0; j < M; ++j)
                for(int k = 0; k < M; ++k)
                    x.mx[i][j] = (x.mx[i][j] + 1ll * mx[i][k] * a.mx[k][j] % MOD) % MOD;
        return x;
    }
}C;

Matrix mat_pow(Matrix mx, long long p) {
    Matrix res;
    res.Tranfer_E();
    for(; p; p >>= 1, mx = mx * mx)
        if(p & 1) res = res * mx;
    return res;
}

void solve(long long res = 0) {
    C = mat_pow(C, n * n - 1);
    memset(temp, 0, sizeof temp);
    for(int i = 0; i < n; ++ i) {
        for(int _k = 0; _k < k; ++ _k) {
            for(int j = 0; j < k; ++ j) {
                temp[i][j] = (temp[i][j] + A[i][_k] * C.mx[_k][j] % MOD) % MOD;
            }
        }
    }
    memset(ans, 0, sizeof ans);
    for(int i = 0; i < n; ++ i) {
        for(int _k = 0; _k < k; ++ _k) {
            for(int j = 0; j < n; ++ j) {
                ans[i][j] = (ans[i][j] + temp[i][_k] * B[_k][j] % MOD) % MOD;
            }
        }
    }

    for(int i = 0; i < n; ++ i)
        for(int j = 0; j < n; ++ j)
            res += ans[i][j];
    cout << res << endl;
}

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(nullptr);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif
    while(cin >> n >> k) {
        memset(C.mx, 0, sizeof C.mx);
        for(int i = 0; i < n; ++ i) {
            for(int j = 0; j < k; ++ j) {
                cin >> A[i][j];
                A[i][j] %= 6;
            }
        }
        for (int i = 0; i < k; ++i) {
            for(int j = 0; j < n; ++ j) {
                cin >> B[i][j];
                B[i][j] %= 6;
            }
        }
        for (int i = 0; i < k; ++i)
            for (int _k = 0; _k < n; ++_k)
                for (int j = 0; j < k; ++j)
                    C.mx[i][j] = (C.mx[i][j] + B[i][_k] * A[_k][j] % MOD) % MOD;
        if(n + k) solve();
        else break;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值