2014 Multi-University Training Contest 9 -- 组队选拔赛三

HDU 4965 Fast Matrix Calculation 

题意:

给你一个n*k的矩阵A,给你一个k*n的矩阵B,C = A*B, 求C^(n*n) 对6取模, 计算结果的元素和?

思路:

如果直接按照它说的做的话,会在矩阵快速幂种产生一个n*n*n的复杂度。 会t。

转换一下:

C^(n*n) = (A*B)^(n*n) = A * (B*A)^(n*(n-1)) * B,

B*A是一个6*6的,这样就可以快速幂了。

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

const int maxn = 1000 + 7;

const int mod = 6;

struct Mar{
    int n,m;
    vector<int> a[maxn];

    void init(){
        for (int i = 0; i < maxn ;++i) a[i].clear();
    }
    void read(int n,int k){
        this->n = n;
        this->m = k;
        int x;
        for (int i = 0; i < n; ++i){
            for (int j = 0; j < k; ++j){
                scanf("%d",&x);
                a[i].push_back(x);
//                scanf("%d",&a[i][j]);
            }
        }
    }

    Mar mul(Mar o){
        Mar ans;
        ans.init();
        ans.n = n; ans.m = o.m;
        for (int i = 0; i < n; ++i){
            for (int j = 0; j < o.m; ++j){
                int sum = 0;
                for (int k = 0; k < m; ++k){
                    sum = (sum + a[i][k]*o.a[k][j]) % mod;
                }
                ans.a[i].push_back(sum);
            }
        }
        return ans;
    }
}A,B;


int n,k;

Mar my_pow(Mar a,int b){
    Mar ans;
//    ans.init();
    for (int i = 0; i < k; ++i){
        ans.a[i].resize(7);
    }
    for (int i = 0; i < k; ++i){
        for (int j = 0; j < k; ++j){
            if (i == j) ans.a[i][j] = 1;
            else ans.a[i][j] = 0;
        }

    }
    ans.n = k; ans.m = k;
    while(b){
        if (b & 1)
            ans = ans.mul(a);
        a = a.mul(a);
        b >>= 1;
    }
    return ans;
}


int main(){

    while(~scanf("%d %d",&n, &k) && (n || k)){
        A.init();
        B.init();
        A.read(n,k);
        B.read(k,n);
//        puts("haha");
        Mar c = B.mul(A);
        c = my_pow(c,n*n-1);
        A = A.mul(c);
        A = A.mul(B);
        int ans=0;
        for (int i = 0; i < A.n; ++i){
            for (int j = 0; j < A.m; ++j){
                ans += A.a[i][j];
            }
        }
        printf("%d\n",ans);
    }

    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值