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':' ');
}
}