数据结构与算法MOOC / 第十二章 高级数据结构 练习题 9:Training little cats(不构造矩阵的终极优化)

本文介绍了如何使用快速幂算法和稀疏矩阵优化来解决数据结构问题。通过变换矩阵的压缩存储,将时间复杂度从O(n^3 log m)降低到O(n log m)。文章详细阐述了矩阵的表示、矩阵乘法以及矩阵与向量的乘法,并讨论了算法的空间和时间效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构与算法MOOC / 第十二章 高级数据结构 练习题 9:Training little cats(不构造矩阵的终极优化)


题目链接

AC代码

#include <cstdio>

#define swap(a, b) if ((a) != (b)) (a) ^= (b), (b) ^= (a), (a) ^= (b)

typedef unsigned long long uint64;

struct Matrix {
   
    uint64 b[101];
    int A[101];
} mat, matBuff;

uint64 results[101], buff[101], n, K, a, b, m;

char cmd[2];

void setMAT() {
   
    for (int i = 0; i <= n; ++i) {
   
        results[i] = 0;
        buff[i] = 0;
        mat.A[i] = i;
        mat.b[i] = 0;
    }
    for (int i = 0; i < K; ++i) {
   
        scanf("%s", cmd);
        switch (*cmd) {
   
            case 'g':
                scanf("%llu", &a);
                ++mat.b[a];
                break;
            case 'e':
                scanf("%llu", &b);
                mat.A[b] = 0;
                mat.b[b] = 0;
                break;
            case 's':
                scanf("%llu%llu", &a, &b);
                swap(mat.A[a], mat.A[b]);
                swap(mat.b[a], mat.b[b]);
                break;
            default:
                break;
        }
    }
}

void matLeftMul(Matrix a, Matrix &b) {
   
    matBuff.A[0] = 0, matBuff.b[0] = 0;
    for (int i = 1; i <= n; ++i) {
   
        matBuff.A[i] = b.A[a.A[i]];
        matBuff.b[i] = a.b[i] + b.b[a.A[i]];
    }
    for (int i = 1; i <= n; ++i) {
   
        b.A[i] = matBuff.A[i];
        b.b[i] = matBuff.b[i];
    }
}

void vecLeftMul(Matrix a, uint64 *b) {
   
    *buff = 0;
    for (int i = 1; i <= n; ++i)
        buff[i] = a.b[i] + b[a.A[i]];
    for (int i = 1; i <= n; ++i)
        b[i] = buff[i];
}


void calcResults() {
   
    while (m) {
   
        if (m & 1) vecLeftMul(mat, results);
        matLeftMul(mat, mat);
        m >>= 1;
    }
}

int main() {
   
    while (scanf("%llu%llu%llu", &n, &m, &K), n | m | K) {
   
        setMAT();
        calcResults();
        for (int i = 1; i <= n; ++i)
            printf("%llu ", results[i]);
        putchar('\n');
    }
}

解题思路

这是一道经典的问题,来自北京大学2009年校内赛。很早以前见过这道题,然后在查到了很多构造矩阵的方法。感觉北大挺喜欢数学类的问题的(毕竟是主打理科)。

这是笔者第一次写快速幂算法,写起挺快的,然后果不其然地就掉入稀疏矩阵的陷阱,被恭喜TLE,然后被提示需要对稀疏矩阵的乘法进行优化。发现网上大多数优化方法都很简单,记录一下每一行每一列是否全0,这样求解的时间代价从 O ( n 3 log ⁡ m ) O(n^3 \log m) O(n3logm)变为了 O ( n 2 log ⁡ m ) O(n^2 \log m) O(n2logm),就可以AC了。但是既然是稀疏矩阵,正好最近刷了些图论的题,就想试试用十字链表练练手吧。写着写着,突然灵光一现,发现了一个进一步把时间代价优化到 O ( n log ⁡ m ) O(n \log m) O(nlogm)的方法。

变换矩阵的构造

根据恭喜我TLE的那篇文章的说法,我们可以把原问题写成这样的形式:
( A b O 1 ) m × ( O 1 ) = ( x ′ 1 ) \begin{pmatrix} A &amp; b \\ O &amp; 1 \end{pmatrix}^m \times \begin{pmatrix} O \\ 1 \end{pmatrix} = \begin{pmatrix} x&#x27; \\ 1 \end{pmatrix} (

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值