1 条题解

  • 0
    @ 2026-10-26 4:22:35

    思路与算法

    先读 n,mn,m 及 n×mn\times m 的矩阵 AA,再读 pp 和 m×pm\times p 的矩阵 BB。结果有 nn 行 pp 列。逐个输出位置 (i,j)(i,j),沿公共维度 k=0,…,m−1k=0,\ldots,m-1 累加 AikBkjA_{ik}B_{kj}。这里 pp 在矩阵 AA 之后输入,不得按其它版本在首行读三个维度。

    矩阵元素可以为负。单项绝对值至 10810^8,最多累加100项,结果绝对值可达 101010^{10},故输入元素、乘法和累加器都采用64位整数。每算完一行按列输出,不必另存整个结果矩阵。

    正确性说明

    固定结果位置 (i,j)(i,j)。内层循环处理完前 tt 项时,累加器恰为 ∑k=0t−1AikBkj\sum_{k=0}^{t-1}A_{ik}B_{kj}:初始零对应空和,每次增加下一项保持不变式。结束时得到定义要求的点积。外层枚举全部 npn p 个位置,每个位置计算一次,故输出恰为 ABAB。64位范围覆盖所有中间部分和,不会改变整数结果。

    复杂度

    存储数组初始化和输入耗时 O(nm+mp)O(nm+mp),每个输出位置累加 mm 项,耗时 O(nmp)O(nmp),输出 O(np)O(np)。总时间 O(nm+mp+nmp+np)O(nm+mp+nmp+np),正维度下可简为 O(nmp)O(nmp)。额外空间 O(nm+mp)O(nm+mp),结果逐项输出无需 O(np)O(np) 缓存。

    易错点

    1. 公共维度是 mm,结果为 n×pn\times p,不要颠倒 AA、BB 或拿 nn 作为累加上限。
    2. pp 要在读完 AA 后再读取。矩阵乘法通常不可交换。
    3. 乘法前就使用64位,不能先以32位算乘积再转换。
    4. 覆盖非方阵、维度1、正负抵消以及正负 101010^{10} 结果。按行输出并保留负号。
    5. 训练数据来源和自编边界均非官方原版;独立答案以任意精度外积累加核验。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m, p;
        cin >> n >> m;
        vector<vector<ll>> a(n, vector<ll>(m));
        for (auto &row : a)
            for (ll &x : row)
                cin >> x;
        cin >> p;
        vector<vector<ll>> b(m, vector<ll>(p));
        for (auto &row : b)
            for (ll &x : row)
                cin >> x;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < p; j++) {
                ll value = 0;
                for (int k = 0; k < m; k++)
                    value += a[i][k] * b[k][j];
                if (j)
                    cout << ' ';
                cout << value;
            }
            cout << '\n';
        }
    }
    
    • 1

    信息

    ID
    1657
    时间
    1000ms
    内存
    512MiB
    难度
    普及−
    标签
    递交数
    1
    已通过
    1
    上传者