题目

一个细胞自动机包含 $n$ 个格子,每个格子的取值为 $0 \sim m-1$。给定距离 $d$,则每次操作是将每个格子的值变为到它的距离不超过 $d$ 的所有格子的在操作之前的值的和除以 $m$ 的余数。给出 $n, m, d, k$ 和自动机各个格子的初始值。你的任务是计算 $k$ 次操作以后各格子的值。($1 \leq n\leq 500, 1 \leq m\leq 10^6, 0 \leq d\leq n/2, 1\leq k\leq 10^7$).

分析

如果我们把 $t$ 次操作以后的各格子值写成列向量 $v_t$,不难发现 $v_{t+1}$ 的每一维都是 $v_t$ 中各维的线性组合,其中的加法和乘法都是在模 $m$ 的剩余系中完成。

每次操作相当于乘以一个 $n \times n $ 矩阵,直接使用矩阵快速幂的复杂度为 $O(n^3logk)$,

由于这里的矩阵比较特殊,是循环矩阵(从第二行开始每一行都是上一行循环右移),

可以证明,两个循环矩阵的乘积仍然为循环矩阵。

因此在存储时只需保存第一行,而计算矩阵乘法时也只需算出第一行即可。这样,矩阵乘法的时间复杂度降为 $O(n^2)$。总时间降为 $O(n^2log k)$,可以承受。

用FFT优化的话可做到 $0(nlognlogk)$.  

$$\begin{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} \times
\begin{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} =
\begin{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 = +;
struct matrix
{
int n;
ll mat[maxn];
matrix(){
memset(mat, , 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 = ;i < A.n;i++)
for(int j = ;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[]=;
while(n)
{
if(n & ) ret = mul(ret, A);
A = mul(A, A);
n >>= ;
}
return ret;
} int main()
{
while(scanf("%lld%lld%lld%lld", &n, &p,&d, &k) == )
{
for(int i = ;i < n;i++) scanf("%lld", &a[i]);
matrix A;
A.n = n;
for(int i = ;i <= d;i++) A.mat[i] = ;
for(int i = n-d; i < n;i++) A.mat[i] = ; A = mpow(A, k); for(int i = ;i < A.n;i++)
{
ll tmp = ;
for(int j = ;j < A.n;j++) tmp = (tmp + A.mat[(j-i+n) % n] * a[j]) % p;
printf("%lld%c", tmp, i == n- ? '\n' : ' ');
}
}
return ;
}

记得开 long long !!

参考链接: https://vjudge.net/status/#un=&OJId=UVALive&probNum=3704&res=0&orderBy=run_id&language=

LA 3704细胞自动机——循环矩阵&&矩阵快速幂的更多相关文章

  1. Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)

    Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...

  2. 洛谷 P4910 帕秋莉的手环 矩阵乘法+快速幂详解

    矩阵快速幂解法: 这是一个类似斐波那契数列的矩乘快速幂,所以推荐大家先做一下下列题目:(会了,差不多就是多倍经验题了) 注:如果你不会矩阵乘法,可以了解一下P3390的题解 P1939 [模板]矩阵加 ...

  3. Qbxt 模拟赛 Day4 T2 gcd(矩阵乘法快速幂)

    /* 矩阵乘法+快速幂. 一开始迷之题意.. 这个gcd有个规律. a b b c=a*x+b(x为常数). 然后要使b+c最小的话. 那x就等于1咯. 那么问题转化为求 a b b a+b 就是斐波 ...

  4. 【BZOJ-1009】GT考试 KMP+DP+矩阵乘法+快速幂

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2745  Solved: 1694[Submit][Statu ...

  5. 矩阵乘法快速幂 codevs 1574 广义斐波那契数列

    codevs 1574 广义斐波那契数列  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond   题目描述 Description 广义的斐波那契数列是指形如 ...

  6. 矩阵乘法快速幂 codevs 1732 Fibonacci数列 2

    1732 Fibonacci数列 2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 在“ ...

  7. BZOJ-1875 HH去散步 DP+矩阵乘法快速幂

    1875: [SDOI2009]HH去散步 Time Limit: 20 Sec Memory Limit: 64 MB Submit: 1196 Solved: 553 [Submit][Statu ...

  8. BZOJ-2326 数学作业 矩阵乘法快速幂+快速乘

    2326: [HNOI2011]数学作业 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1564 Solved: 910 [Submit][Statu ...

  9. BZOJ-2875 随机数生成器 矩阵乘法快速幂+快速乘

    题目没给全,吃X了... 2875: [Noi2012]随机数生成器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 1479 Solved: 829 ...

随机推荐

  1. 使用JMeter进行Apache Kafka负载测试

    1.卡夫卡负载测试 在这个Apache Kafka教程中,我们将了解如何使用Apache JMeter,如何在Apache Kafka上执行Kafka负载测试.此外,这个Kafka负载测试教程教我们如 ...

  2. time包 — 汇总

    time包学习 package main; import ( "time" "fmt" ) func main() { //time.Time代表一个纳秒精度的 ...

  3. [hdu 4841]圆桌问题 | 约瑟夫问题 STL-vector

    原题 问题描述: 经典的约瑟夫问题,有2n个人,其中n个好人n个坏人,使得删去n人后,剩下的全为好人.m为每次数的人数. n<=32767 题解: 首先考虑n的范围,暴力肯定行不通,所以会想到线 ...

  4. matlab 2017b 支持的C编译器

    在电力电子开发领域,matlab是非常重要的工具,随着系统仿真和编程开发的不断融合,在matlab中使用混合编程并进行仿真验证,甚至是软件工程里面,源文件的自生成.编译以及一键程序下载等功能,都是越来 ...

  5. [洛谷P5323][BJOI2019]光线

    题目大意:有$n$层玻璃,每层玻璃会让$a\%$的光通过,并把$b\%$的光反射.有一束光从左向右射过,问多少的光可以透过这$n$层玻璃 题解:事实上会发现,可以把连续的几层玻璃合成一层玻璃,但是要注 ...

  6. SDOI2019 Round2

    这鬼家伙已经咕了好久了-- SDOIR2的题目挺好玩的- 快速查询(???) 不难发现所有的操作都可以通过区间打Tag实现 那么可以维护两个标记\(a,b\)表示序列中的数为\(x\)时实际表示的值是 ...

  7. Codeforces Round #569 Div. 1

    A:n-1次操作后最大值会被放到第一个,于是暴力模拟前n-1次,之后显然是循环的. #include<bits/stdc++.h> using namespace std; #define ...

  8. 记录:拷贝gitblit里的项目使用git命令clone、pull、push等,出现一直在加载,卡住没反应的问题

    俺想克隆别人gitblit里的其中一个版本库(俺在别人gitblit有权限) 懂得git的道友们,都应该知道克隆一个公共项目,随便找到,打开git终端,输入git clone 项目地址就行了 到了俺这 ...

  9. 【洛谷 P1659】 [国家集训队]拉拉队排练(manacher)

    题目链接 马拉车+简单膜你 #include <cstdio> #include <cstring> #include <algorithm> using name ...

  10. php后台实现页面跳转的方法-转载

    地址:http://blog.csdn.net/abandonship/article/details/6459104 其中方法三的js代码在tp框架使用存在故障,一个是需要把代码写在一起(可能也不需 ...