P9668 [ICPC2022 Jinan R] Torch 题解

news/2024/10/5 14:52:33/文章来源:https://www.cnblogs.com/JiaY19/p/18287915

思路

考虑使用矩阵模拟这个过程。

首先,我们可以设初值为:

\[\begin{bmatrix} 0&1 \end{bmatrix} \]

表示瘦子初始走 \(0\) 米,胖子初始走 \(1\) 米。

考虑瘦子走一步。

由于瘦子每走一步都不能超过胖子,我们可以使用 \((\min,+)\) 矩乘来维护这个性质。

那么瘦子走一步是:

\[\begin{bmatrix} 1&inf\\ -1&0\\ \end{bmatrix} \]

同样,胖子走一步是:

\[\begin{bmatrix} 0&inf\\ inf&1\\ \end{bmatrix} \]

不走是:

\[\begin{bmatrix} 0&inf\\ inf&0\\ \end{bmatrix} \]

我们可以把每个循环中的所有过程求出来。

由于循环的长度是 \(\operatorname{lcm}(a_1+b_1,a_2+b_2)\)

我们将相邻的合并以后就只会有最多 \(2(a_1+b_1+a_2+b_2)\) 项。

做一个前缀和即可。

时间复杂度:\(O(n\log n)\)

可能会有一点卡空间,卡一卡就可以了。

Code

/*! 以渺小启程,以伟大结束。! Created: 2024/07/03 09:01:00
*/
#include <bits/stdc++.h>
using namespace std;#define x first
#define y second
#define int long long
#define mp(x, y) make_pair(x, y)
#define eb(...) emplace_back(__VA_ARGS__)
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)
inline void JYFILE19();using i64 = long long;
using PII = pair<int, int>;bool ST;
const int N = 1e6 + 10;
const int I = 1e18 + 10;
const int mod = 998244353;struct Mat {int a00, a01, a10, a11;inline friend Mat operator*(const Mat&a, const Mat&b) {return {min(a.a00 + b.a00, a.a01 + b.a10),min(a.a00 + b.a01, a.a01 + b.a11),min(a.a10 + b.a00, a.a11 + b.a10),min(a.a10 + b.a01, a.a11 + b.a11)};}
};
const Mat sz = {1, I,-1, 0};
const Mat pz = {0, I, I, 1};
const Mat sj = {0, I, I, 0};
const Mat pj = {0, I, I, 0};
struct Nod {int a00, a01;inline friend Nod operator*(const Nod&a, const Mat&b) {return {min(a.a00 + b.a00, a.a01 + b.a10),min(a.a00 + b.a01, a.a01 + b.a11)};}
};int q[N];
int t[N * 8];
Mat d[N];
Mat c[N * 8];inline Mat power(Mat x, int y) {Mat res = x; y--;while (y) {if (y & 1) res = res * x;x = x * x, y /= 2;}return res;
}inline void solve() {int a1, b1, a2, b2, n;cin >> a1 >> b1;cin >> a2 >> b2;cin >> n;Nod cs = {0, 1};int p1 = 0, p2 = 0, s1 = 0, s2 = 0, p = 0, ti = 0;Mat zy;do {Mat cur;int sy = 1e9;if (p1 == 0) cur = pz, sy = min(a1 - s1, sy);if (p1 == 1) cur = pj, sy = min(b1 - s1, sy);if (p2 == 0) cur = cur * sz, sy = min(a2 - s2, sy);if (p2 == 1) cur = cur * sj, sy = min(b2 - s2, sy);++p, t[p] = sy, c[p] = cur, ti += t[p];s1 += sy, s2 += sy;if (p1 == 0 && s1 == a1) p1 = 1, s1 = 0;if (p1 == 1 && s1 == b1) p1 = 0, s1 = 0;if (p2 == 0 && s2 == a2) p2 = 1, s2 = 0;if (p2 == 1 && s2 == b2) p2 = 0, s2 = 0;} while (p1 || p2 || s1 || s2);fro(i, 1, p) t[i] = t[i - 1] + t[i];fro(i, 1, n) {cin >> q[i];int w = q[i], l = w / ti;if (l) {w -= ti * l;}if (w) {int x = upper_bound(t + 1, t + p + 1, w) - t;d[i] = c[x];}}fro(i, 1, p) c[i] = power(c[i], t[i] - t[i - 1]);fro(i, 2, p) c[i] = c[i - 1] * c[i];fro(i, 1, n) {Nod ed = cs;int l = q[i] / ti;if (l) {ed = ed * power(c[p], l), q[i] -= ti * l;}if (q[i]) {int x = upper_bound(t + 1, t + p + 1, q[i]) - t;if (x - 1)ed = ed * c[x - 1], q[i] -= t[x - 1];if (q[i])ed = ed * power(d[i], q[i]);}cout << ed.a00 << "\n";}
}signed main() {JYFILE19();int t;cin >> t;while (t--) {solve();}return 0;
}bool ED;
inline void JYFILE19() {// freopen("", "r", stdin);// freopen("", "w", stdout);srand(random_device{}());ios::sync_with_stdio(0), cin.tie(0);double MIB = fabs((&ED - &ST) / 1048576.), LIM = 1024;cerr << "MEMORY: " << MIB << endl, assert(MIB <= LIM);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/739524.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第一次学习Java的碎碎念

2024年夏新的学习开始了; 今天做了什么? 在B站上收藏了黑马程序员学习Java的教学视频,观看了几篇入门教程,暂时学会了如何打开CMD,以及几个常见的CMD命令,例如盘符名称:、dir、cd目录、cd..、cls、exit等等,做了一个练习(利用cmd打开qq),学会了如何把应用程序的路径…

测试标题

测试摘要\[a /ge b /eq c \]

Java反射与Fastjson的危险反序列化

Preface 在前文中,我们介绍了 Java 的基础语法和特性和 fastjson 的基础用法,本文我们将深入学习fastjson的危险反序列化以及预期相关的 Java 概念。 什么是Java反射? 在前文中,我们有一行代码 Computer macBookPro = JSON.parseObject(preReceive,Computer.class); 这行代…

Win10双屏设置 之 鼠标不能从中间划过 问题解决

Win10双屏设置 之 鼠标不能从中间划过解决-百度经验 (baidu.com)

比赛获奖的武林秘籍:03 好的创意选取-获得国奖的最必要前提

本文主要介绍了大学生电子计算机类比赛和创新创业类比赛创意选取的重要性,并列举了好的创意选取和坏的创意选取的例子,同时说明了好的创意选取具有哪些特点,同时对常见的创意选取途径与来源进行了基本介绍。比赛获奖的武林秘籍:03 好的创意选取-获得国奖的最必要前提 摘要 …

阶段测试

Sre网络班阶段测试 一:用sed 命令修改/etc/fstab文件,删除文件中的空行,注释行,并保留文件备份(7分) 答案写这里:二: 用 find 命令查找出 /var/ 目录中大于1M且以db结尾的文件(7分) 答案写这里:三: 先判断当前主机是否安装了nginx包,如果没安装,则执行命令安装,…

时间序列分析专题——利用SPSS专家建模器进行建模

SPSS的专家建模器可以自动识别数据,给出最适合的模型,本章通过三个例题介绍如何使用SPSS实现时间序列分析。由于本人对时间序列分析的理解尚浅,做出模型后在论文上的呈现形式需要取查阅资料,以便更好地在论文上呈现 在此之前,我们还需要了解时间序列分析的一些基础的名词 …

如何在ubuntu上设置清华源

如何在ubuntu上设置清华源 apt介绍 apt(Advanced Packaging Tool)是一个在 Debian 和 Ubuntu 中的 Shell 前端软件包管理器。 apt 命令提供了查找、安装、升级、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。 apt 命令执行需要超级管理员权限(root)。 操作 …

c++ u7-02-高精度乘法

本节课作业: 链接:https://pan.baidu.com/s/13-FC86jSHGziRDA8lqzimg?pwd=owv1 提取码:owv1高精度乘法    #include<iostream> #include<cstdio> #include<cstring> using namespace std; string x , y; int a[50010] , b[50010] , c[50010…

node-red的基本指令

1. inject->debug输入到输出,调试结果在右边如果选择时间戳的话,可以选择立即执行,或者周期性,持续执行inject除了时间戳还有一些其他输入项可以选择inject选择json文件输出写好json文件之后点击格式化json,可以校对文件格式payload.number可以让输出只输出number的内容…

lombokjunit

lombok&junit 1 lombok先去官网或者maven仓库下载jar包https://mvnrepository.com/导入第三方包到项目中右键lib文件夹,点击add as library默认jvm不解析第三方注解,需要手动开启使用//@Setter // 生成set方法 1 //@Getter // 生成get方法 2 //@ToString // 生…