题目链接
题目描述
求解思路
- 调整矩阵运算的顺序:根据矩阵运算符合结合律这一特点,对运算式的顺序进行调整。根据题目给出的数据范围,我们可以先将 K T ( d ∗ n ) K^T(d*n) KT(d∗n) 矩阵和 V ( n ∗ d ) V(n*d) V(n∗d) 进行乘法运算。在将 W W W 矩阵和 Q ( n ∗ d ) Q(n*d) Q(n∗d) 矩阵相乘的结果运算出来,最后将两者做乘法得到最终结果。
- 复杂度分析:
- 如果按照顺序直接运算:
- W W W 矩阵和 Q ( n ∗ d ) Q(n*d) Q(n∗d) 矩阵相乘: T 1 = O ( n d ) T_1=O(nd) T1=O(nd)。
- 和 K T ( d ∗ n ) K^T(d*n) KT(d∗n) 矩阵相乘: T 2 = O ( n 2 d ) T_2=O(n^2d) T2=O(n2d)。
- 和 V ( n ∗ d ) V(n*d) V(n∗d) 矩阵相乘: T 3 = O ( n 2 d ) T_3=O(n^2d) T3=O(n2d)。
- 综上,时间复杂度为: T = O ( n 2 d ) T=O(n^2d) T=O(n2d)。
- 按照交换后的顺序进行运算:
- K T ( d ∗ n ) K^T(d*n) KT(d∗n) 矩阵和 V ( n ∗ d ) V(n*d) V(n∗d) 矩阵相乘 T 1 = O ( n d 2 ) T_1=O(nd^2) T1=O(nd2)。
- W W W 矩阵和 Q ( n ∗ d ) Q(n*d) Q(n∗d) 矩阵相乘: T 2 = O ( n d ) T_2=O(nd) T2=O(nd)。
- 两个运算结果在相乘: T 3 = O ( n d 2 ) T_3=O(nd^2) T3=O(nd2)。
- 综上,时间复杂度为: T = O ( n d 2 ) T=O(nd^2) T=O(nd2)。
- 因为 n < = 1 0 4 n<=10^4 n<=104 而 d < = 20 d<=20 d<=20,因此对于调整运算顺序之后的时间消耗一定比之前要小得多。
- 如果按照顺序直接运算:
实现代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n, d;
int i, j, k;
n = in.nextInt();
d = in.nextInt();
int[][] Q = new int[n][d];
int[][] K_T = new int[d][n];
int[][] V = new int[n][d];
int[] W = new int[n];
// 读取Q
for (i = 0; i < n; i ++) {
for (j = 0; j < d; j ++) {
Q[i][j] = in.nextInt();
}
}
// 读取K
for (i = 0; i < n; i ++) {
for (j = 0; j < d; j ++) {
K_T[j][i] = in.nextInt();
}
}
// 读取V
for (i = 0; i < n; i ++) {
for (j = 0; j < d; j ++) {
V[i][j] = in.nextInt();
}
}
// 读取W
for (i = 0; i < n; i ++) {
W[i] = in.nextInt();
}
// 计算W*Q
for (i = 0; i < n; i ++) {
for (j = 0; j < d; j ++) {
Q[i][j] *= W[i];
}
}
// 计算K_T*V
long[][] T1 = new long[d][d];
for (i = 0; i < d; i ++) {
for (j = 0; j < d; j ++) {
for (k = 0; k < n; k ++) {
T1[i][j] += K_T[i][k] * V[k][j];
}
}
}
// 计算并输出Q*T1
long[][] T2 = new long[n][d];
for (i = 0; i < n; i ++) {
for (j = 0; j < d; j ++) {
for (k = 0; k < d; k ++) {
T2[i][j] += Q[i][k] * T1[k][j];
}
System.out.print(T2[i][j] + " ");
}
System.out.println();
}
}
}