题面:UVA1386 Cellular Automaton

矩阵乘法+快速幂解法:

这是一个比较裸的有点复杂需要优化的矩乘快速幂,所以推荐大家先做一下下列洛谷题目练练手:

(会了,差不多就是多倍经验题了)

注:如果你还不会矩阵乘法,可以移步了解一下P3390的题解

P1939 【模板】矩阵加速(数列)

P3390 【模板】矩阵快速幂

P1962 斐波那契数列

P4910 帕秋莉的手环

P4838 P哥破解密码

然后讲一下本题,读题我们发现这个环上所进行的 k 次操作都是一模一样的,还是相邻的数的和,于是想到用矩阵快速幂来写。

解题思路:

我们可以根据 d 的值来建出基础矩阵,举个例子(样例):

					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

这是样例每一次操作所对应的乘法矩阵。我们要求出 k 次操作后的环上的元素等同于乘以 k 次这个矩阵,而这个过程可以直接用快速幂优化成log复杂度。

于是我们便可以光明正大的提交,然后光荣 TLE 了

为什么呢?我们看到数据范围:$ n \leq 500 $ !众所周知:矩阵乘法中矩阵上每一个元素都会被用行乘列的方式更新,所以复杂度为 \(n^3\),在乘上快速幂的一个log n ,不TLE才怪!

优化方案:

于是我们尝试优化一下(把那个 $ n^3 $ 降到 $ n^2 $ ):我们再看到上面样例的矩阵,可以发现它的下一行等于上一行所有的 1 向右移一位。所以我们进行矩阵乘法时可以不更新矩阵的每一个位置,而是只更新它的第一行(将它压缩一下)其它几行可以通过第一行推出来。

例如:

					0 2 1 1 2

我们可以通过这一行推出整个矩阵(向右移一位):

					0 2 1 1 2
2 0 2 1 1
1 2 0 2 1
1 1 2 0 2
2 1 1 2 0

于是乎,我们写一个新的”矩阵乘法“代码如下:

void cheng(ll a[],ll b[]){
for(int i=1;i<=n;i++)//预处理 1
res[i]=0,s[1][i]=b[i];
for(int i=2;i<=n;i++){
s[i][1]=s[i-1][n];
for(int j=2;j<=n;j++)
s[i][j]=s[i-1][j-1];
}// 解压一维矩阵,复杂度不会变回 n^3!
for(int i=1;i<=n;i++)
for(int k=1;k<=n;k++)
res[i]+=(a[k]*s[i][k])%m,res[i]%=m;
for(int i=1;i<=n;i++)a[i]=res[i];
}// 本题专用“矩阵乘法”
//请不要直接给a数组赋值,不然后果自负!

然后在用快速幂优化一下:

while(k){
if(k&1)cheng(ans,base);
cheng(base,base);
k>>=1;
}

完整代码:

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm> #define ll long long
#define db double
#define inf 0x7fffffff using namespace std; const int l=501;
int n,m,d,k;
ll s[l][l];
ll ans[l],base[l],res[l];
// ans=(answer),base(基础矩阵),res=(result)
// s数组是用来解压矩阵的(将一维矩阵换成二维) inline ll qr(){
char ch;
while((ch=getchar())<'0'||ch>'9');
ll res=ch^48;
while((ch=getchar())>='0'&&ch<='9')
res=(res<<1)+(res<<3)+(ch^48);
return res;
} void cheng(ll a[],ll b[]){
for(int i=1;i<=n;i++)//预处理 1
res[i]=0,s[1][i]=b[i];
for(int i=2;i<=n;i++){
s[i][1]=s[i-1][n];
for(int j=2;j<=n;j++)
s[i][j]=s[i-1][j-1];
}// 解压一维矩阵,复杂度不会变回 n^3!
for(int i=1;i<=n;i++)
for(int k=1;k<=n;k++)
res[i]+=(a[k]*s[i][k])%m,res[i]%=m;
for(int i=1;i<=n;i++)a[i]=res[i];
}// 本题专用“矩阵乘法”
//请不要直接给a数组赋值,不然后果自负! int main(){
while(scanf("%d%d%d%d",&n,&m,&d,&k)!=EOF){
for(int i=1;i<=n;i++)//预处理 2
ans[i]=qr(),base[i]=0;
for(int i=0;i<=d;i++)//单位矩阵
base[1+i]=base[(n-i)%n+1]=1;
while(k){
if(k&1)cheng(ans,base);
cheng(base,base);
k>>=1;
}// 只有四行的快速幂
for(int i=1;i<n;++i){
printf("%lld ",ans[i]);
}printf("%lld\n",ans[n]);
}
return 0;
} //预处理 1:将res数组归零,将b数组赋值给s数组第一维以便压缩 //预处理 2:给ans数组赋初值,将单位矩阵清零

注:解压矩阵会消耗很多时间,也可以不解压,但乘起来会有些麻烦(蒟蒻手残,就不压行了吧)。

UVA1386 【Cellular Automaton】题解的更多相关文章

  1. 【POJ】3150 Cellular Automaton(矩阵乘法+特殊的技巧)

    http://poj.org/problem?id=3150 这题裸的矩阵很容易看出,假设d=1,n=5那么矩阵是这样的 1 1 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 ...

  2. UVA 1386 - Cellular Automaton(循环矩阵)

    UVA 1386 - Cellular Automaton option=com_onlinejudge&Itemid=8&page=show_problem&category ...

  3. [POJ 3150] Cellular Automaton (矩阵高速幂 + 矩阵乘法优化)

    Cellular Automaton Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 3048   Accepted: 12 ...

  4. POJ 3150 Cellular Automaton(矩阵快速幂)

    Cellular Automaton Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 3504 Accepted: 1421 C ...

  5. POJ - 3150 :Cellular Automaton(特殊的矩阵,降维优化)

    A cellular automaton is a collection of cells on a grid of specified shape that evolves through a nu ...

  6. POJ 3150 Cellular Automaton(矩阵高速幂)

    题目大意:给定n(1<=n<=500)个数字和一个数字m,这n个数字组成一个环(a0,a1.....an-1).假设对ai进行一次d-step操作,那么ai的值变为与ai的距离小于d的全部 ...

  7. POJ 3150 Cellular Automaton --矩阵快速幂及优化

    题意:给一个环,环上有n块,每块有个值,每一次操作是对每个点,他的值变为原来与他距离不超过d的位置的和,问k(10^7)次操作后每块的值. 解法:一看就要化为矩阵来做,矩阵很好建立,大白书P157页有 ...

  8. LA 3704 Cellular Automaton

    题意概述: 等价地,本题可以转化为下面的问题: 考虑$n \times n$的$0-1$矩阵$A$,在第$i$行上第$[-d+i, d+i]$(模$n$意义下)列对应的元素为$1$,其余为$0$.求$ ...

  9. POJ 3150 Cellular Automaton(矩阵乘法+二分)

    题目链接 题意 : 给出n个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次转化后,数组变成什么. 思路 :下述来自here 首先来看一下Sample里的第一组 ...

随机推荐

  1. BZOJ3309 DZY Loves Math(莫比乌斯反演+线性筛)

    一通正常的莫比乌斯反演后,我们只需要求出g(n)=Σf(d)*μ(n/d)的前缀和就好了. 考虑怎么求g(n).当然是打表啊.设n=∏piai,n/d=∏pibi .显然若存在bi>1则这个d没 ...

  2. BZOJ 1180: [CROATIAN2009]OTOCI

    1180: [CROATIAN2009]OTOCI Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 989  Solved: 611[Submit][S ...

  3. 【bzoj3926】 Zjoi2015—诸神眷顾的幻想乡

    http://www.lydsy.com/JudgeOnline/problem.php?id=3926 (题目链接) 题意 给出一棵树,每个节点有一个编号,范围在${[0,9]}$.一个序列是指树上 ...

  4. 一次绕过防火墙获取RCE以及提权到root权限的渗透过程

    本文是关于Apache struts2 CVE-2013-2251是由于导致执行远程命令的影响而被高度利用的漏洞.简而言之, 通过操纵以“action:”/”redirect:”/”redirectA ...

  5. MongoDB ShardingCluster

    sharding集群中的组件: 1.mongos:router,可以通过keepalived实现高可用. 2.config server:元数据服务器,这里要借助zookeeper存放配置信息. 3. ...

  6. 前端学习 -- Xhtml语法规范

    Xhtml语法规范 HTML中不区分大小写,但是尽量使用小写: HTML的注释不能嵌套: 标签必须结构完整{要么成对出现,要么自结束标签,虽然浏览器会帮我们修正一些不符合规范的内容} 标签可以嵌套但是 ...

  7. bzoj4784【zjoi2017】仙人掌

    题目描述 如果一个无自环无重边无向连通图的任意一条边最多属于一个简单环,我们就称之为仙人掌.所谓简单环即不经过 重复的结点的环. 现在九条可怜手上有一张无自环无重边的无向连通图,但是她觉得这张图中的边 ...

  8. laravel 中的 toSql 获取带参数的 sql 语句

    默认情况下,toSql 获取到的 sql 里面的参数使用 "?" 代替的,如下: DB::table('user')->where('id', 1)->toSql(); ...

  9. [case]filesystem problem

    e2fsck -Nov-) fsck.ext4: Superblock invalid, trying backup blocks... fsck.ext4: Bad magic number in ...

  10. awk 脚本同时解析多个文件

    ARGC        The number of command line arguments (does not include                   options to gawk ...