【循环矩阵+矩阵快速幂】Cellular Automaton UVA - 1386

本文介绍了一种解决特定类型变换问题的方法,利用循环矩阵和矩阵快速幂来优化计算过程。通过对输入序列进行多次变换,文章详细展示了如何降低时间与空间复杂度。

Think:
1知识点:循环矩阵+矩阵快速幂
2题意:输入n(1<=n<=500), m(1<=n<=1000000), d(0<=d<(n/2)), k(1<=k<=10000000)然后输入一个n个数的环,数的范围为[0,m-1],然后进行k次变换,变换为:取环中当前元素,然后取其左边d个数,取其右边d个数,然后相加取模m,询问经过k次变换之后的序列
3题意思考:
(1):写出系数矩阵,会发现系数矩阵n*n太大,空间复杂度和时间复杂度都相对过大,进而通过循环矩阵性质,将空间复杂度由二维矩阵优化至一维矩阵,矩阵乘法的时间复杂度由n^3优化至n^2
4反思:
(1):函数形参传入为常变量时,无法在函数内改变传入的常变量的值
(2):矩阵运算的性质以及特殊矩阵的性质需要复习回顾

以下为Accepted代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

LL mod;

struct Matrix{
    LL v[504];
};

Matrix multiply(const Matrix &a, const Matrix &b, int Matrix_len);
Matrix matrix_pow(Matrix x, int k, int Matrix_len);

LL rec[504], ans[504];

int main(){
    int n, d, k, i, j;
    while(~scanf("%d %lld %d %d", &n, &mod, &d, &k)){
        Matrix x;
        for(i = 0; i < n; i++)
            scanf("%lld", &rec[i]);
        memset(x.v, 0, sizeof(x.v));
        x.v[0] = 1;
        for(i = 1; i <= d; i++){
            x.v[i] = 1;
        }
        for(i = n-1; i >= n-d; i--){
            x.v[i] = 1;
        }
        Matrix y = matrix_pow(x, k-1, n);
        memset(ans, 0, sizeof(ans));
        for(i = 0; i < n; i++){
            for(j = 0; j < n; j++){
                ans[i] += y.v[(j-i+n)%n]*rec[j];
                ans[i] %= mod;
            }
        }
        for(i = 0; i < n; i++)
            printf("%lld%c", ans[i], i == n-1? '\n': ' ');
    }
    return 0;
}
Matrix multiply(const Matrix &a, const Matrix &b, int Matrix_len){
    Matrix tmp;
    memset(tmp.v, 0, sizeof(tmp.v));
    for(int i = 0; i < Matrix_len; i++){
        for(int j = 0; j < Matrix_len; j++){
            tmp.v[i] += a.v[j]*b.v[(i-j+Matrix_len)%Matrix_len];
            tmp.v[i] %= mod;
        }
    }
    return tmp;
}
Matrix matrix_pow(Matrix x, int k, int Matrix_len){
    Matrix tmp = x;
    while(k){
        if(k & 1)
            tmp = multiply(tmp, x, Matrix_len);
        x = multiply(x, x, Matrix_len);
        k >>= 1;
    }
    return tmp;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值