首页 > 其他分享 >P9668 [ICPC2022 Jinan R] Torch 题解

P9668 [ICPC2022 Jinan R] Torch 题解

时间:2024-07-06 21:08:46浏览次数:8  
标签:ICPC2022 sy const Mat min int 题解 a00 Jinan

思路

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

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

\[\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);
}

标签:ICPC2022,sy,const,Mat,min,int,题解,a00,Jinan
From: https://www.cnblogs.com/JiaY19/p/18287915

相关文章

  • CF292C Beautiful IP Addresses 题解(两种写法)
    题意一个IP地址是一个32位的2进制整数,分成四组8位的2进制整数(没有前导0)。比如说,0.255.1.123 是一个正确的IP地址,而0.256.1.123 和 0.255.1.01 不是正确的。定义一个合法的回文IP地址为BeautifulIPAddress(回文地址就是去掉“.”后是个回文字符串的地......
  • 沪越联赛 - 2024年6月月赛Div2 题解
    问题A:替换题目描述小明每次注释的时候都写\(n\)个/。小红看了小明的程序,觉得太难看了,那么多/,所以决定把这些没用的/都去掉。小红定义了一个宏命令,每次可以将所有连续的\(m\)个/替换成空(注意不是空格)小明得知了小红的企图后非常着急,因为他知道光把/都去掉,那么原......
  • C++题解(3) 信息学奥赛一本通: 1013:温度表达转化 洛谷:B2013 温度表达转化 土豆编程:M
    【题目描述】利用公式 C=5×(F−32)÷9C=5×(F−32)÷9(其中CC表示摄氏温度,FF表示华氏温度)进行计算转化,输入华氏温度FF,输出摄氏温度CC,要求精确到小数点后55位。【输入】输入一行,包含一个实数FF,表示华氏温度。(F≥−459.67)(F≥−459.67)【输出】输出一行,包含一个......
  • [AGC064D] Red and Blue Chips 题解
    题目链接点击打开链接题目解法挺牛的题这种计数本质不同的结果的题,一个很不错的切入口是判断结果的合法性令B的总数为\(m\)我们把结果串先挂在第\(m\)个B上考虑从后往前枚举原串(最后一个B不枚举),相当于我们在倒序模拟操作过程枚举到B,我们相当于要把后面的一个B......
  • HT-014 Div3 扫雷 题解 [ 绿 ] [ 二维差分 ]
    分析观察到是曼哈顿距离\(\ler\)的范围可以扫到,联想到如下图形:左边是\(r=1\)可以扫到的范围,右边是\(r=2\)可以扫到的范围。于是,我们只要对这样的图形在\(1000*1000\)的格子里差分一下就好了。但这样的复杂度是\(O(nm)\)的,会死的很惨。优化不难发现这个图形是一......
  • HT-014 Div3 跳棋 题解 [ 黄 ] [ 并查集 ] [ 树型结构 ]
    分析依旧是一个连通块题。观察题面不难发现两个重要性质:一个跳棋只能以它旁边的两个跳棋为中点跳跃,且满足跳跃路线中除中点以外没有其它跳棋阻挡。只有我们的跳棋可以移动。跳棋的操作具有可逆性/对称性。第三条性质可以这么理解,就是一个跳棋跳过去之后,它还可以跳回来。......
  • [POI2015] WYC 题解
    [POI2015]WYC显然矩阵乘法发现点数和边权非常小,所以可以考虑拆点把每个点拆为\(u_1\),\(u_2\),\(u_3\),初始:\(u_1\tou_2\),\(u_2\tou_3\),每一条加边:\(u+(w-1)\timesn\tov\)因为\(k\)非常大,所以考虑倍增优化注意:答案会爆longlong,需要使用unsignedlonglong//Pro......
  • python-docx库 写入docx时中文不适配问题,中文异常问题解决办法。
    python-docx库写入docx时中文不适配问题,中文异常问题解决办法。通过以下方法可以成功将正文修改为宋体字体。这个是全文设置。fromdocx.oxml.nsimportqndoc=Document()doc.styles['Normal'].font.name=u'宋体'doc.styles['Normal']._element.rPr.rFonts.set(qn('w:......
  • ZeroMQ最全面试题解读(3万字长文)
    目录解释ZeroMQ是什么,它的主要用途是什么?ZeroMQ支持哪些通信模式?描述一下ZeroMQ中的“消息”和“消息帧”如何在C++中初始化一个ZeroMQ上下文?在ZeroMQ中,如何创建一个套接字并将其绑定到特定端口?解释什么是“管道模式”(PipePattern)说明如何使用ZeroMQ进行点对点通信Zer......
  • 题解:CF1256D Binary String Minimizing
    贪心。数据范围\(n\le10^{6}\),因此我们要用时间复杂度为\(\mathcal{O}\left(n\right)\)的算法来解决这个问题。思路从左至右扫一遍序列,如果遇到\(10\),则要将这个\(0\)交换到前面的位置。由于是字典序最小,\(0\)应该尽量在最高位。现在需要知道这个\(0\)被交换到哪......