HPUoj 1183: 线代 ( 矩阵快速幂

1183: 线代

Description

学过线性代数后,Ocean又有了新的难题。
现在Ocean有两个矩阵AA和BB,大小分别为n∗xn∗x和x∗mx∗m。现在Ocean想知道新矩阵C=(A∗B)tC=(A∗B)t。
但是输出矩阵太麻烦了,你只需要告诉他CC矩阵元素之和对666666取余的结果即可。
所有测试数据保证nn 等于 mm。请认真读题

C=A∗BC=A∗B程序实现:
假设AA矩阵是n∗xn∗x的,BB矩阵是x∗mx∗m的,则得到的CC矩阵是n∗mn∗m的。
程序实现C=A∗BC=A∗B如下:

int n, x, m;
int A[1001][10], B[10][1001], C[1001][1001];
int i, j, k;
for(i = 0; i < n; i++) {
    for(j = 0; j < m; j++) {
        C[i][j] = 0;
    }
}
for(i = 0; i < n; i++) {
    for(k = 0; k < x; k++) {
        if(A[i][k] == 0) continue;
        for(j = 0; j < m; j++) {
            C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % 666;
        }
    }
}

Input

第一行输入一个整数TT,代表有TT组测试数据。
每组数据占多行,第一行依次输入四个整数n,x,m,tn,x,m,t分别代表上面提到的信息。
接下来有nn行,每行输入xx个元素代表AA矩阵。
后面再有xx行,每行输入mm个元素代表BB矩阵。

注:1<=T<=100,1<=n,m,t<=1000,1<=x<=6,1<=1<=T<=100,1<=n,m,t<=1000,1<=x<=6,1<=矩阵元素 <=66。

Output

输出一个整数,代表CC矩阵元素之和对666666取余后的结果。

Sample Input

2
10 3 10 1000
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1
2 2 2 2 2 2 2 2 2 2 
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
10 4 10 1000
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
7 7 7 7 7 7 7 7 7 7 
7 7 7 7 7 7 7 7 7 7 
7 7 7 7 7 7 7 7 7 7 
7 7 7 7 7 7 7 7 7 7 

Sample Output

396
340

题解:

题目要求的是 (a*b)^t%mod 的和,a*b = c[n][m] 显然不能进行矩阵快速幂 但是b*a = c[x][x] 就可以了
这里用到的矩阵的性质
我们可以转化为a*((b*a)^t)*b

AC代码

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

#define LL long long
#define CLR(a,b) memset(a,(b),sizeof(a))

const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5+10;
const int mod = 666;
int n, m, xx;
int a[1005][10], b[10][1005];
int aa[1005][10], bb[1005][1005];
struct node
{
    int arr[10][10];
};
node mul(node x,node y)
{
    node ans;
    CLR(ans.arr,0);
    for(int i = 0; i < xx; i++) {
        for(int j = 0; j < xx; j++) {
            for(int k = 0; k < xx; k++) {
                ans.arr[i][j] += x.arr[i][k]*y.arr[k][j];
                ans.arr[i][j] %= mod;
            }

        }
    }
    return ans;
}
node pow_mod(node x, int u)
{
    node ans;
    for(int i = 0; i < xx; i++)
        for(int j = 0; j < xx; j++)
            if(i == j) ans.arr[i][j] = 1;
            else ans.arr[i][j] = 0;
    while(u) {
        if(u&1) ans = mul(ans,x);
        x = mul(x,x);
        u >>= 1;
    }
    return ans;

}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--) {
        int t;
        node x, y, z;
        node nn, mm;
        CLR(aa,0);
        CLR(bb,0);
        CLR(z.arr,0);
        cin>>n>>xx>>m>>t;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < xx; j++)
                cin>>a[i][j];
        for(int i = 0; i < xx; i++)
            for(int j = 0; j < m; j++)
                cin>>b[i][j];
        for(int i = 0; i < xx; i++) {
            for(int j = 0; j < xx; j++) {
                for(int k = 0; k < m; k++) {
                    z.arr[i][j] += b[i][k]*a[k][j];
                    z.arr[i][j] %= mod;                }
            }
        }
        node zz = pow_mod(z,t-1);
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < xx; j++) {
                for(int k = 0; k < xx; k++) {
                    aa[i][j] += a[i][k]*zz.arr[k][j];
                    aa[i][j] %= mod;
                }
            }
        }
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                for(int k = 0; k < xx; k++) {
                    bb[i][j] += aa[i][k]*b[k][j];
                    bb[i][j] %= mod;
                }
            }
        }
        int sum = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                sum = (sum+bb[i][j]) % mod;
            }
        }
        printf("%d\n",sum%mod);
    }
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值