POJ 3150 Cellular Automaton 题解(循环矩阵+矩阵快速幂)

题目链接

题目大意

给定一个n格的环,现在有个距离d,每次变化把环和他周围距离d以内的格子相加,结果mod m,问经过k次变换之后,环上的各个数字

题目思路

前置知识

循环矩阵它的行向量的每个元素都是前一个行向量各元素依次右移一个位置得到的结果。图片如下

性质
循环矩阵遵循代数运算法则。对于两个循环矩阵 A 与 B 来说,A + B 也是循环矩阵。AB 也是循环矩阵,并且 AB=BA。

正文

很显然,每一个状态都是和上一个状态有关。而且看数据范围显然是矩阵快速幂。
矩阵很好想,每个位置对应周围几个位置为1,其余位置为0,但是这个矩阵有500,有点大,直接n^3 去求矩阵不太合适,然后观察发现这个矩阵是个循环矩阵,循环矩阵相乘的话,只需要保存一行即可,然后用n^2的时间就足够计算了

代码

//这个矩阵乘法的写法可以学习

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 505;

int n, m, d, k;
ll ans[maxn], matrix[maxn];
ll c[maxn+5];

void mul(ll a[], ll b[]) {
    memset(c, 0, sizeof(c));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            c[i] += a[j] * b[(i-j+n) % n];
    for (int i = 0; i < n; i++)
        b[i] = c[i] % m;
}

int main() {
    while (scanf("%d%d%d%d", &n, &m, &d, &k) != EOF) {
        memset(ans, 0, sizeof(ans));
        memset(matrix, 0, sizeof(matrix));
        for (int i = 0; i < n; i++)
            cin>>ans[i];

        for (int i = 0; i <= n-1; i++)
            matrix[i] =   (i<=d||n-i<=d);

        while (k) {
            if (k & 1){
                mul(matrix, ans);
            }
            mul(matrix, matrix);
            k >>= 1;
        }
        for (int i = 0; i <= n - 1; i++)
            printf("%lld%c", ans[i],i==n-1?'\n':' ');
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值