uva1386 Cellular Automaton

137 篇文章 0 订阅

A cellular automaton is a collection of cells on a grid of specified
shape that evolves through a number of discrete time steps according
to a set of rules that describe the new state of a cell based on the
states of neighboring cells. The order of the cellular automaton is
the number of cells it contains. Cells of the automaton of order n are
numbered from 1 to n. The order of the cell is the number of different
values it may contain. Usually, values of a cell of order m are
considered to be integer numbers from 0 to m−1. One of the most
fundamental properties of a cellular automaton is the type of grid on
which it is computed. In this problem we examine the special kind of
cellular automaton — circular cellular automaton of order n with cells
of order m. We will denote such kind of cellular automaton as n,m−
automaton. A distance between cells i and j in n,m-automaton is defined
as min(|i − j|,n −|i − j|). A denvironment of a cell is the set of
cells at a distance not greater than d. On each d-step values of all
cells are simultaneously replaced by new values. The new value of cell
i after d-step is computed as a sum of values of cells belonging to
the d-enviroment of the cell i modulo m. The following picture shows
1-step of the 5,3-automaton. The problem is to calculate the state of
the n,m-automaton after k d-steps. Input The input file contains
several test cases, each of them consists of two lines, as described
below. The first line of the input contains four integer numbers n, m,
d, and k (1 ≤ n ≤ 500, 1 ≤ m ≤ 1000000, 0 ≤ d < n 2 , 1 ≤ k ≤
10000000). The second line contains n integer numbers from 0 to m−1 —
initial values of the automaton’s cells. Output For each test case,
write to the output, on a line by itself, the values of the
n,m-automaton’s cells after k d-steps.

容易发现可以采用矩阵快速幂,但是这样做是 O(n3logk) 的,无法承受。因为相伴矩阵比较特殊,是一个循环矩阵,可以根据第一行得出下面任意元素,所以矩阵的保存和计算都只用对第一行操作,复杂度降为 O(n2logk)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
int n,m,d,k;
struct mat
{
    int a[510];
    mat operator * (const mat &rhs) const
    {
        mat ret;
        for (int i=0;i<n;i++)
        {
            ret.a[i]=0;
            for (int j=0;j<n;j++)
              ret.a[i]=(ret.a[i]+(LL)a[j]*rhs.a[((i-j)%n+n)%n]%m)%m;
        }
        return ret;
    }
}a,base;
int main()
{
    int i;
    while (scanf("%d%d%d%d",&n,&m,&d,&k)==4)
    {
        for (i=0;i<n;i++)
          scanf("%d",&a.a[i]);
        for (i=0;i<n;i++)
          base.a[i]=(i<=d||i>=n-d);
        while (k)
        {
            if (k&1) a=a*base;
            base=base*base;
            k>>=1;
        }
        for (i=0;i<n;i++)
          printf("%d%c",a.a[i],i==n-1?'\n':' ');
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值