CH3401 石头游戏(矩阵快速幂加速递推)
题目链接:传送门
题目:
石头游戏 0x30「数学知识」例题
描述
石头游戏在一个 n 行 m 列 (≤n,m≤) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这10个数字指明。
操作序列是一个长度不超过6且循环执行、每秒执行一个字符的字符串。每秒钟,所有格子同时执行各自操作序列里的下一个字符。序列中的每个字符是以下格式之一: 数字0~:表示拿0~9个石头到该格子。
NWSE:表示把这个格子内所有的石头推到相邻的格子,N表示上方,W表示左方,S表示下方,E表示右方。
D:表示拿走这个格子的所有石头。 给定每种操作序列对应的字符串,以及网格中每个格子对应的操作序列,求石头游戏进行了 t 秒之后,石头最多的格子里有多少个石头。在游戏开始时,网格是空的。
输入格式 第一行4个整数n, m, t, act。
接下来n行,每行m个字符,表示每个格子对应的操作序列。
最后act行,每行一个字符串,表示从0开始的每个操作序列。
输出格式 一个整数:游戏进行了t秒之后,所有方格中最多的格子有多少个石头。
样例输入 1E
E 样例输出 样例解释 这是另一个类似于传送带的结构。左边的设备0间隔地产生石头并向东传送。设备1向右传送,直到设备2。10秒后,总共产生了5个石头,2个在传送带上,3个在最右边。
题目注:
答案会超int,要用longlong,看了眼数据t的范围好像是1e9,其他的无所谓了。
思路:
(以下参考李煜东《算法竞赛进阶指南》)
这题数据范围都没给齐,要是直接做肯定一脸懵逼。不过《算法竞赛进阶指南》上作为了矩阵快速幂的例题,那就用矩阵快速幂了。。
要找两个东西,状态矩阵和转移矩阵。
状态矩阵:
题目中的状态是一个n*m的矩阵,而一般情况下矩阵快速幂要求用一维向量作为状态矩阵,所以就把这个状态拉成长度为n*m的向量了。。。
原矩阵的(i, j) 为状态矩阵中的F[(i-1)*m + j],不妨令num(i, j) = (i-1)*m + j。那么在状态矩阵中就是F[num(i, j)]了。
另外,令F[0] = 1,作为常数1,方便转移出常数。
转移矩阵:
假设ch为原矩阵对应位置i, j对应时刻k的操作:
① 如果ch为"N",则Ak(num(i, j), num(i-1, j)) = 1; ch 为 "W"、"E"、"S"也是同理。被转移的位置判断一下是否合法。
② 如果ch为[0-9],则Ak(0, num(i, j)) = ch-'0'(加上数值),Ak(num(i, j), num(i, j)) = 1(保留上个状态的值)
③ 保证F[0]不变,Ak(0, 0) = 1;
④ Ak的其它部分为0。
不同的时刻有不同的转移矩阵,但是由于[1-6]的最小公倍数为60(6为操作序列的最大长度),所以直接处理k = 0-59时刻的所有状态矩阵,然后分解t = q*60 + r(0 ≤ r < 60),
令$A =\prod_{k = 0}^{59}A_{k}$,则$F_{t} = F_{0} * A^{q} * \prod_{k=0}^{r-1}A_{k}$。
代码:
#include <bits/stdc++.h> using namespace std;
typedef long long ll;
const int MAX_NM = ; int n, m, t, act;
string opt[];
string acts[];
ll F[MAX_NM], A[][MAX_NM][MAX_NM], AAA[MAX_NM][MAX_NM]; inline int num(int i, int j) {
return (i-)*m + j;
} void mul(ll f[MAX_NM], ll a[MAX_NM][MAX_NM]) {
ll c[MAX_NM];
memset(c, , sizeof c);
for (int j = ; j < MAX_NM; j++)
for (int k = ; k < MAX_NM; k++)
c[j] += f[k] * a[k][j];
memcpy(f, c, sizeof c);
} void mulb(ll a[MAX_NM][MAX_NM], ll b[MAX_NM][MAX_NM]) {
ll c[MAX_NM][MAX_NM];
memset(c, , sizeof c);
for (int i = ; i < MAX_NM; i++)
for (int j = ; j < MAX_NM; j++)
for (int k = ; k < MAX_NM; k++)
c[i][j] += a[i][k]*b[k][j];
memcpy(a, c, sizeof c);
} void mulself(ll a[MAX_NM][MAX_NM]) {
ll c[MAX_NM][MAX_NM];
memset(c, , sizeof c);
for (int i = ; i < MAX_NM; i++)
for (int j = ; j < MAX_NM; j++)
for (int k = ; k < MAX_NM; k++)
c[i][j] += a[i][k]*a[k][j];
memcpy(a, c, sizeof c);
} void init()
{
memset(A, , sizeof A);
memset(F, , sizeof F);
F[] = ;
for (int k = ; k < ; k++) {
A[k][][] = ;
for (int i = ; i <= n; i++) {
for (int j = ; j <= m; j++) {
int index = opt[i-][j-] - '';
int indey = k % acts[index].size();
char ch = acts[index][indey]; if (isupper(ch)) {
switch (ch) {
case 'N':
if (i- >= )
A[k][num(i, j)][num(i-, j)] = ; break;
case 'S':
if (i+ <= n)
A[k][num(i, j)][num(i+, j)] = ; break;
case 'W':
if (j- >= )
A[k][num(i, j)][num(i, j-)] = ; break;
case 'E':
if (j+ <= m)
A[k][num(i, j)][num(i, j+)] = ; break;
case 'D':
A[k][num(i, j)][num(i, j)] = ;
}
}
if (isdigit(ch)) {
A[k][num(i, j)][num(i, j)] = ;
A[k][][num(i, j)] = ch - '';
} }
}
}
for (int i = ; i < MAX_NM; i++)
AAA[i][i] = ;
for (int k = ; k < ; k++)
mulb(AAA, A[k]);
} int main()
{
cin >> n >> m >> t >> act;
for (int i = ; i < n; i++)
cin >> opt[i];
for (int i = ; i < act; i++)
cin >> acts[i];
init();
int q = t/;
int r = t%;
// t = q*60 + r;
for (; q; q >>= ) {
if (q&)
mul(F, AAA);
mulself(AAA);
}
for (int i = ; i < r; i++)
mul(F, A[i]);
ll ans = ;
for (int i = ; i < MAX_NM; i++)
ans = max(ans, F[i]);
cout << ans << endl;
return ;
}
CH3401 石头游戏(矩阵快速幂加速递推)的更多相关文章
- CH 3401 - 石头游戏 - [矩阵快速幂加速递推]
题目链接:传送门 描述石头游戏在一个 $n$ 行 $m$ 列 ($1 \le n,m \le 8$) 的网格上进行,每个格子对应一种操作序列,操作序列至多有 $10$ 种,分别用 $0 \sim 9$ ...
- 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 ...
- 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 ...
- 洛谷P1357 花园(状态压缩 + 矩阵快速幂加速递推)
题目链接:传送门 题目: 题目描述 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(<=N<=^).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻 ...
- HDU5950 Recursive sequence (矩阵快速幂加速递推) (2016ACM/ICPC亚洲赛区沈阳站 Problem C)
题目链接:传送门 题目: Recursive sequence Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total ...
- [bzoj1008](HNOI2008)越狱(矩阵快速幂加速递推)
Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 In ...
- POJ3070 Fibonacci(矩阵快速幂加速递推)【模板题】
题目链接:传送门 题目大意: 求斐波那契数列第n项F(n). (F(0) = 0, F(1) = 1, 0 ≤ n ≤ 109) 思路: 用矩阵乘法加速递推. 算法竞赛进阶指南的模板: #includ ...
- [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)
Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...
- 2019.2.25考试T1, 矩阵快速幂加速递推+单位根反演(容斥)
\(\color{#0066ff}{题解}\) 然后a,b,c通过矩阵加速即可 为什么1出现偶数次3没出现的贡献是上面画绿线的部分呢? 考虑暴力统计这部分贡献,答案为\(\begin{aligned} ...
随机推荐
- .Net 读取配置文件 xml
直接解析XML文件 1.System.Xml.Linq命名空间下提供可以使用linq查询的类,使用linq to xml读取也很方便. 2.还可以使用System.Xml.Serialization类 ...
- Ipan笔记-2
其实二级联动下拉选择框很简单的, 参考: https://www.cnblogs.com/zhangmiaomiao/p/6013533.html ============== 关于$.each和 $ ...
- 【论文笔记】Dynamic Routing Between Capsules
Dynamic Routing Between Capsules 2018-09-16 20:18:30 Paper:https://arxiv.org/pdf/1710.09829.pdf%20 P ...
- Linux 软连接 (ln命令)
这是linux中一个非常重要命令.它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s,具体用法是:ln -s 源文件 目标文件. 当我们需要在不同的目录,用到相同的文件 ...
- LeetCode--018--四数之和(java)
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满 ...
- 覃超:Facebook的项目开发流程和工程师的绩效管理机制
覃超:Facebook的项目开发流程和工程师的绩效管理机制 http://mp.weixin.qq.com/s?__biz=MjM5MDE0Mjc4MA==&mid=2650992350&am ...
- 『Python』库安装
1.安装指定版本的tensorflow 虽然官网有4种安装方式,并且推荐用anaconda的方式,但是有时候我们需要指定版本的tensorflow,而pip可以做到. 比如我装的是anaconda3. ...
- Grafana + Prometheus 监控PostgreSQL
效果图 部署环境 服务器名称 IP地址 部署业务 备注 部署agent sht-sgmhadoopcm-01 172.16.101.54 PostgreSQL 监控服务器.被监控服务器 node_ex ...
- Pyhon中运算符的使用
1. a & b python中的&延续了C/C++的含义,表示位运算. 例如 3 & 4:3&5:6&7 3 & 4 = (011)2 & ( ...
- 【C/C++】内存基础
1. 基本数据类型 short s = 0x4142; // 16进制 char c = *(char*)&s; cout << c << endl; 我的电脑上输出为 ...