HPUoj 1183: 线代 ( 矩阵快速幂

来源:互联网 发布:淘宝u站怎么进入 编辑:程序博客网 时间:2024/06/05 13:33

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

210 3 10 10001 1 11 1 11 1 11 1 11 1 11 1 11 1 11 1 11 1 11 1 12 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 2 2 2 2 210 4 10 10001 2 3 41 2 3 41 2 3 41 2 3 41 2 3 41 2 3 41 2 3 41 2 3 41 2 3 41 2 3 47 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

396340

题解:

题目要求的是 (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;}