BZOJ 2973 石头游戏 矩乘加速递推
FFFFFFF,看了一上午才看懂,又调了一中午。。。。。我终于明白为何自己如此菜了qwq
这个题加速的思路是:因为每个序列的长度小于6,他们的lcm是60,所以六十次以后就会回到原来的序列。
加速的就是这一个个重复的60次
我们把60个转移矩阵乘起来(结合律),设为d,然后有x=t/60就是有多少个d,算出d的x次方(快速幂)
然后不足60次的一个个乘起来就好了
至于如何建转移矩阵。。。模拟一下吧(我搞了一上午qwq):
e[k]是第k次的转移矩阵,取石子从0里面取(因此e[k][0][0]都是1)
对于这个矩阵,可以理解为 e[第k次][从哪个状态来][到哪个状态去]
因为矩阵乘不就是ret[i][j]+=a[i][k]*b[k][j],其中b就是转移矩阵(再不理解可以吧i那一维给去了)
PS:sizeof时注意是指针的大小还是数组的大小。。。因为这个调了一中午。。。。
#include<cstdio>
#include<iostream>
#include<cstring>
#define ll long long
#define R register int
using namespace std;
inline ll g() {
register ll ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,t,p,q;
int a[][],cnt[][];
ll f[],d[][],e[][][];
ll ans;
char b[][],s[],ch;
inline int pos(int i,int j) {return (i-)*m+j;}
inline ll max(ll a,ll b) {return a>b?a:b;}
// inline void print(ll *a) { cout<<endl<<"fasdfas"; //调试输出
// for(R i=0;i<=p;++i) printf("%lld ",a[i]); cout<<endl;
// }
// inline void print2(ll a[70][70]) { cout<<"eeewee";
// for(R i=0;i<=p;++i,cout<<endl<<" ") for(R j=0;j<=p;++j) printf("%lld ",a[i][j]);
// }
inline void mul1(ll a[][],ll b[][]) {
register ll ret[][]; memset(ret,,sizeof(ret));
for(R i=;i<=p;++i) for(R k=;k<=p;++k) if(a[i][k]) for(R j=;j<=p;++j)
ret[i][j]+=a[i][k]*b[k][j];
memcpy(a,ret,sizeof(ret));
}
inline void mul2(ll f[],ll a[][]) {
register ll ret[]; memset(ret,,sizeof(ret));
for(R j=;j<=p;++j) for(R k=;k<=p;++k)
ret[j]+=f[k]*a[k][j];
memcpy(f,ret,sizeof(ret));
}
inline void build() {
for(R k=;k<=;e[k][][]=,++k) for(R i=;i<=n;++i) for(R j=;j<=m;++j) {
R x=a[i][j],p=cnt[i][j];
if(b[x][p]>=''&&b[x][p]<='') {
e[k][][pos(i,j)]=b[x][p]-'';
e[k][pos(i,j)][pos(i,j)]=;
} else if(b[x][p]=='N'&&i>) e[k][pos(i,j)][pos(i-,j)]=;
else if(b[x][p]=='W'&&j>) e[k][pos(i,j)][pos(i,j-)]=;
else if(b[x][p]=='S'&&i<n) e[k][pos(i,j)][pos(i+,j)]=;
else if(b[x][p]=='E'&&j<m) e[k][pos(i,j)][pos(i,j+)]=;
cnt[i][j]=(p+)%strlen(b[x]);
} if(t>) {memcpy(d,e[],sizeof(e[])); for(R i=;i<=;++i) mul1(d,e[i]);}
}
signed main() {
n=g(),m=g(),t=g(),q=g(); p=n*m;
for(R i=;i<=n;++i) {
scanf("%s",s+);
for(R j=;j<=m;++j) ch=s[j],a[i][j]=(ch^)+;
} for(R i=;i<=q;++i) scanf("%s",&b[i]);
build(); f[]=;
for(R i=t/;i;i>>=,mul1(d,d)) if(i&) mul2(f,d);
for(R i=,lim=t%;i<=lim;++i) mul2(f,e[i]);
for(R i=;i<=p;++i) ans=max(ans,f[i]); printf("%lld\n",ans);
//while(1);
}
别颓废,至少看起来你懂了。2019.05.10
BZOJ 2973 石头游戏 矩乘加速递推的更多相关文章
- CH 3401 - 石头游戏 - [矩阵快速幂加速递推]
题目链接:传送门 描述石头游戏在一个 $n$ 行 $m$ 列 ($1 \le n,m \le 8$) 的网格上进行,每个格子对应一种操作序列,操作序列至多有 $10$ 种,分别用 $0 \sim 9$ ...
- [模板][题解][Luogu1939]矩阵乘法加速递推(详解)
题目传送门 题目大意:计算数列a的第n项,其中: \[a[1] = a[2] = a[3] = 1\] \[a[i] = a[i-3] + a[i - 1]\] \[(n ≤ 2 \times 10^ ...
- HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950 Farmer John likes to play mathematics games with ...
- POJ3070 Fibonacci(矩阵快速幂加速递推)【模板题】
题目链接:传送门 题目大意: 求斐波那契数列第n项F(n). (F(0) = 0, F(1) = 1, 0 ≤ n ≤ 109) 思路: 用矩阵乘法加速递推. 算法竞赛进阶指南的模板: #includ ...
- bzoj2004公交线路——DP+矩阵加速递推
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2004 求方案数,想到DP: 因为两个站间距离<=p,所以每p个站中所有车一定都会停靠至 ...
- HDU 1757 矩阵快速幂加速递推
题意: 已知: 当x<10时:f(x)=x 否则:f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + --+ a9 * f(x-10); 求:f(x ...
- 【csp模拟赛3】bridge.cpp--矩阵加速递推
题目描述 穿越了森林,前方有一座独木桥,连接着过往和未来(连接着上一题和下一题...). 这座桥无限长. 小 Q 在独木桥上彷徨了.他知道,他只剩下了 N 秒的时间,每一秒的时间里,他会向 左或向右移 ...
- luogu题解 P1707 【刷题比赛】矩阵加速递推
题目链接: https://www.luogu.org/problemnew/show/P1707 分析: 洛谷的一道原创题,对于练习矩阵加速递推非常不错. 首先我们看一下递推式: \(a[k+2]= ...
- CH3401 石头游戏(矩阵快速幂加速递推)
题目链接:传送门 题目: 石头游戏 0x30「数学知识」例题 描述 石头游戏在一个 n 行 m 列 (≤n,m≤) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这10个数 ...
随机推荐
- ACM学习历程—UESTC 1226 Huatuo's Medicine(数学)(2015CCPC L)
题目链接:http://acm.uestc.edu.cn/#/problem/show/1226 题目就是构造一个对称的串,除了中间的那个只有1个,其余的两边都是对称的两个,自然答案就是2*n-1. ...
- mysql绿色安装
先下载需要的文件: MySQL5.1(绿色).rar 和 MySQL-Front_v5.3(绿色版).rar 都是绿色免安装版 1.解压MySQL Server 5.1.rar到MySQL Serve ...
- bzoj 3924 幻想乡战略游戏 —— 动态点分治
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3924 参考了博客:https://blog.csdn.net/qq_34564984/art ...
- 排成一行的li之间的间隙问题
现象 对于ul下li排成一行的布局(即li的display由list-item设为inline-block): 情况1 如果这些li在书写的时候有换行或者有空格,且ul本身的font-size不为0, ...
- 使用svnadmin对VisualSVN进行项目迁移
使用svnadmin对VisualSVN进行项目迁移 导出1> 启动命令行cmd2> 运行%VISUALSVN_SERVER%\bin\svnadmin dump PATH-TO-REPO ...
- 查看,上传crushmap命令
标签(空格分隔): ceph,ceph运维,crushmap 查看crushmap命令 从mon节点获取crushmap: # ceph osd getcrushmap -o crush.map 反编 ...
- 【转】深刻理解render 和 redirect_to
由于最近老是在表单提交后出现没有反应的现象,发现是在action中的使用render 和 redirect_to的原因,于是就想搞清楚他两真正的区别在哪里,上一遍的blog也谈到了这二者的区别,但是有 ...
- Ruby 局部变量做block参数
Ruby中使用yield语句调用block时可以带有参数,参数值见传送个相关联的block.如果传给block的参数是已经存在的局部变量,那么这些变量即为block的参数,他们的值可能会因block的 ...
- ES6学习之数组扩展
扩展运算符(...将数组分割为用逗号分割的参数序列) console.log(...[1,2,3]) //1 2 3 可替换数组的apply写法: function test(x,y,z){ cons ...
- [原创]SQL表值函数:把用逗号分隔的字符串转换成表格数据
我们日常开发过程中,非常常见的一种需求,把某一个用逗号或者/或者其他符号作为间隔的字符串分隔成一张表数据. 在前面我们介绍了 [原创]SQL 把表中字段存储的逗号隔开内容转换成列表形式,当然按照这 ...