UVA1386 【Cellular Automaton】题解
矩阵乘法+快速幂解法:
这是一个比较裸的有点复杂需要优化的矩乘快速幂,所以推荐大家先做一下下列洛谷题目练练手:
(会了,差不多就是多倍经验题了)
注:如果你还不会矩阵乘法,可以移步了解一下P3390的题解
然后讲一下本题,读题我们发现这个环上所进行的 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】题解的更多相关文章
- 【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 ...
- UVA 1386 - Cellular Automaton(循环矩阵)
UVA 1386 - Cellular Automaton option=com_onlinejudge&Itemid=8&page=show_problem&category ...
- [POJ 3150] Cellular Automaton (矩阵高速幂 + 矩阵乘法优化)
Cellular Automaton Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 3048 Accepted: 12 ...
- POJ 3150 Cellular Automaton(矩阵快速幂)
Cellular Automaton Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 3504 Accepted: 1421 C ...
- POJ - 3150 :Cellular Automaton(特殊的矩阵,降维优化)
A cellular automaton is a collection of cells on a grid of specified shape that evolves through a nu ...
- POJ 3150 Cellular Automaton(矩阵高速幂)
题目大意:给定n(1<=n<=500)个数字和一个数字m,这n个数字组成一个环(a0,a1.....an-1).假设对ai进行一次d-step操作,那么ai的值变为与ai的距离小于d的全部 ...
- POJ 3150 Cellular Automaton --矩阵快速幂及优化
题意:给一个环,环上有n块,每块有个值,每一次操作是对每个点,他的值变为原来与他距离不超过d的位置的和,问k(10^7)次操作后每块的值. 解法:一看就要化为矩阵来做,矩阵很好建立,大白书P157页有 ...
- LA 3704 Cellular Automaton
题意概述: 等价地,本题可以转化为下面的问题: 考虑$n \times n$的$0-1$矩阵$A$,在第$i$行上第$[-d+i, d+i]$(模$n$意义下)列对应的元素为$1$,其余为$0$.求$ ...
- POJ 3150 Cellular Automaton(矩阵乘法+二分)
题目链接 题意 : 给出n个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次转化后,数组变成什么. 思路 :下述来自here 首先来看一下Sample里的第一组 ...
随机推荐
- zookeeper如何实现负载均衡的?(具体连接哪一个zookeeper服务器的选择?)阿里面试
如果想了解web 6大负载均衡算法,参考:六大Web负载均衡原理与实现 主要是三点:负载均衡算法,健康检查和会话保持 1:首先,我们要了解,我们的应用程序,比如java web程序,里面配置了10个z ...
- linux下tomcat、jenkins环境搭建
1.安装JDK 我不列出来了,自行百度 java -version 2.安装tomcat (1)将下载的tomcat压缩包 tar -zxvf apache-tomcat-8.5.29.tar.gz ...
- Java Junit测试框架
Java Junit测试框架 1.相关概念 Ø JUnit:是一个开发源代码的Java测试框架,用于编写和运行可重复的测试.它是用于单元测试框架体系xUnit的一个实例(用于java语言).主要 ...
- 应该更新的Java知识之常用程序库
摘自:http://www.blogbus.com/dreamhead-logs/226738702.html 在很多人眼中,Java已经是一门垂垂老矣的语言,但并不妨碍Java世界依然在前进.如果你 ...
- ThinkPHP 5.x远程命令执行漏洞分析与复现
0x00 前言 ThinkPHP官方2018年12月9日发布重要的安全更新,修复了一个严重的远程代码执行漏洞.该更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的 ...
- rsync同步公网yum源搭建本地yum仓库
镜像同步公网yum源上游yum源必须要支持rsync协议,否则不能使用rsync进行同步. centos源:rsync://rsync.mirrors.ustc.edu.cn/centos/ epel ...
- mysqlbinlog- 处理二进制日志文件的实用工具 学习笔记
参考 MySQL 5.5官方简体中文参考手册完美版 8.6 节 调用: shell> mysqlbinlog [option] log-files... mysqlbinlog支持下面选项: ...
- Android L开发指南
导语:Android下一代操作系统“ L”对开发者意味着什么?ART模式能否让应用的体验超越苹果? 刚刚结束的 Google I/O大会上,Android下一代操作系统“ L”带来不少惊喜.新系统运行 ...
- 解题:TJOI 2015 弦论
题面 好像是个经典问题,然而我没做过 建SAM,然后经过每个节点的子串数目就可以求了,多个相同子串算一个的话就把所有siz都搞成$1$,否则就是$right$集合的大小,然后就是常见的递推 求第$k$ ...
- 【agc003D】Anticube
Portal --> agc003D Description 给你\(n\)个数,要从里面选出最多的数满足这些选出来的数中任意两个数的乘积都不是立方数 Solution (为什么感觉最近这种解法 ...