题面: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. SCRIPT7002: XMLHttpRequest: 网络错误 0x2efe, 由于出现错误 00002efe 而导致此项操作无法完成

    google中带中文参数可能查询,但是在IE带中文参数不能查询:报如下错误 SCRIPT7002: XMLHttpRequest: 网络错误 0x2efe, 由于出现错误 00002efe 而导致此项 ...

  2. Python Matplotlib绘图库 安装

    一般我们在做科学计算的时候,首先会想到的是matlab,但是呢,一想到matlab安装包那么大,我就有点不想说什么了. Matplotlib 是python最著名的绘图库,它提供了一整套和matlab ...

  3. ACM数论之旅13---容斥原理(一切都是命运石之门的选择(=゚ω゚)ノ)

    容斥原理我初中就听老师说过了,不知道你们有没有听过(/≧▽≦)/ 百度百科说: 在计数时,必须注意没有重复,没有遗漏. 为了使重叠部分不被重复计算,人们研究出一种新的计数方法. 这种方法的基本思想是: ...

  4. 自己用过的web软件tools软件以及玩过的游戏

    三年大学世界 最经常用的web网站估计就是淘宝了   最经常使用的工具软件也就是   Microsoft office,而最经常玩的游戏就是英雄联盟了一款pvp对战游戏 淘宝自不必说 可以称为国内最大 ...

  5. jquery datatables 添加跳转到指定页功能

    项目中使用了jquery datatables 作为我们的数据表格组件,但是分页上没有跳转到指定页,需要自己重新写.解决方法如下: 在设置dataTables的默认属性里设置它的drawCallbac ...

  6. vue & keep-alive & activated

    vue & keep-alive & activated vue 生命周期 钩子函数 缓存 http://www.cnblogs.com/nekoooo/p/6442077.html ...

  7. HDU4641_K-string

    若它的一个子串出现的次数不少于K次,那么这个子串就是一个K-string. 现给出原串,每次可以向该串后面添加一个字符或者询问当前有多少个不同的K-string. 在线添加查询,解法直指SAM. 其实 ...

  8. linux系统日志__ratelimit: N callbacks suppressed

    报错 今天线上遇到故障,php进行因为段错误退出了,系统日志中的kernel报错如下: Feb 25 22:25:11 web_server_01 kernel: __ratelimit: 250 c ...

  9. js判断浏览器语言实现网站国际化

    一般国际化的网站至少是有中.英文两种语言的,然后就是在不同的语言环境下使用不同的语言页面. 1.实现原理 一般实现这种功能的方法,无非就是两种, 第一种,判断浏览器语言类型: 第二种,判断ip所属国家 ...

  10. [洛谷P4723]【模板】线性递推

    题目大意:求一个满足$k$阶齐次线性递推数列$a_i$的第$n$项. 即:$a_n=\sum\limits_{i=1}^{k}f_i \times a_{n-i}$ 题解:线性齐次递推,先见洛谷题解, ...