LA 3704细胞自动机——循环矩阵&&矩阵快速幂
Posted lfri
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 3704细胞自动机——循环矩阵&&矩阵快速幂相关的知识,希望对你有一定的参考价值。
题目
一个细胞自动机包含 $n$ 个格子,每个格子的取值为 $0 sim m-1$。给定距离 $d$,则每次操作是将每个格子的值变为到它的距离不超过 $d$ 的所有格子的在操作之前的值的和除以 $m$ 的余数。给出 $n, m, d, k$ 和自动机各个格子的初始值。你的任务是计算 $k$ 次操作以后各格子的值。($1 leq nleq 500, 1 leq mleq 10^6, 0 leq dleq n/2, 1leq kleq 10^7$).
分析
如果我们把 $t$ 次操作以后的各格子值写成列向量 $v_t$,不难发现 $v_{t+1}$ 的每一维都是 $v_t$ 中各维的线性组合,其中的加法和乘法都是在模 $m$ 的剩余系中完成。
每次操作相当于乘以一个 $n imes n $ 矩阵,直接使用矩阵快速幂的复杂度为 $O(n^3logk)$,
由于这里的矩阵比较特殊,是循环矩阵(从第二行开始每一行都是上一行循环右移),
可以证明,两个循环矩阵的乘积仍然为循环矩阵。
因此在存储时只需保存第一行,而计算矩阵乘法时也只需算出第一行即可。这样,矩阵乘法的时间复杂度降为 $O(n^2)$。总时间降为 $O(n^2log k)$,可以承受。
用FFT优化的话可做到 $0(nlognlogk)$.
$$egin{bmatrix}
1 & 1 & 0 & 0 & 1\
1 & 1 & 1 & 0 & 0 \
0 & 1& 1& 1 & 0\
0 & 0 & 1 & 1 & 1\
1 & 0 & 0 & 1 & 1
end{bmatrix} imes
egin{bmatrix}
1 & 1 & 0 & 0 & 1\
1 & 1 & 1 & 0 & 0 \
0 & 1& 1& 1 & 0\
0 & 0 & 1 & 1 & 1\
1 & 0 & 0 & 1 & 1
end{bmatrix} =
egin{bmatrix}
3 & 2 & 1 & 1 & 2\
2 & 3 & 2 & 1 & 1\
1 & 2 & 3 & 2 & 1\
1 & 1 & 2 & 3 & 2\
2 & 1 & 1 & 2 & 3
end{bmatrix}$$
#include<cstdio> #include<cstring> using namespace std; typedef long long ll; const int maxn = 500+10; struct matrix { int n; ll mat[maxn]; matrix(){ memset(mat, 0, sizeof(mat)); } }; ll n, p, d, k; ll a[maxn]; matrix mul(matrix A, matrix B) //矩阵相乘,这里A=B,且都是n x n的方阵 { matrix ret; ret.n = A.n; for(int i = 0;i < A.n;i++) for(int j = 0;j < B.n;j++) ret.mat[i] = (ret.mat[i] + A.mat[j] * B.mat[(j-i+A.n)%A.n]) % p; return ret; } matrix mpow(matrix A, int n) { matrix ret; ret.n = A.n; ret.mat[0]=1; while(n) { if(n & 1) ret = mul(ret, A); A = mul(A, A); n >>= 1; } return ret; } int main() { while(scanf("%lld%lld%lld%lld", &n, &p,&d, &k) == 4) { for(int i = 0;i < n;i++) scanf("%lld", &a[i]); matrix A; A.n = n; for(int i = 0;i <= d;i++) A.mat[i] = 1; for(int i = n-d; i < n;i++) A.mat[i] = 1; A = mpow(A, k); for(int i = 0;i < A.n;i++) { ll tmp = 0; for(int j = 0;j < A.n;j++) tmp = (tmp + A.mat[(j-i+n) % n] * a[j]) % p; printf("%lld%c", tmp, i == n-1 ? ‘ ‘ : ‘ ‘); } } return 0; }
记得开 long long !!
参考链接: https://vjudge.net/status/#un=&OJId=UVALive&probNum=3704&res=0&orderBy=run_id&language=
以上是关于LA 3704细胞自动机——循环矩阵&&矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章