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;
}