当前位置: 首页 > news >正文

【题解】AT_agc003_e [AGC003E] Sequential operations on Sequence

我怎么不会这个啊()

先考虑一个(并非)简单的情况:若参数序列 \(q\) 满足 \(q_1<q_2<\ldots<q_Q\)\(q\) 序列单调递增:

利用经典结论:对于任意正整数 \(x,y\),下面两个情况中至少有一个成立:

  • \(x\bmod y=x\)
  • \(x\bmod y\le \frac x2\)

其实就是辗转相除的时间复杂度证明

于是考虑对于相邻两个参数 \(q_i,q_{i+1}\),考虑特殊处理掉前面 \(\lfloor\frac{q_{i+1}}{q_i}\rfloor\) 个完整的段,剩余长为 \(q_{i+1}\bmod q_i\) 的段直接暴力递归处理,二分找出第一个会更新的位置,根据上面的分析可以知道每次操作长度至少减半,总时间复杂度不会超过对数量级。因此总时间复杂度为 \(O(n\log^2n)\),满足题目给出的限制。


对于 \(q\) 序列不单调递增的情况,容易发现对于两个相邻的位置 \(q_i,q_{i+1}\) 若有 \(q_i\ge q_{i+1}\) 那么前一个操作一定没用,用单调栈处理即可得到 \(q\) 单调递增的情况。因此总时间复杂度仍为 \(O(n\log^2n)\) 可以通过。

// #pragma GCC optimze(3, "Ofast", "inline", "unroll-loops")
#include <bits/stdc++.h>
#define int long long
using namespace std;
using i64 = long long;const int mod = 998244353;
const int G = 3;inline int power(int a, int b, int c)
{int ans = 1;while (b){if (b & 1)ans = ans * a % c;a = a * a % c, b >>= 1;}return ans;
}
inline int inversion(int x) { return power(x, mod - 2, mod); }inline void chkmin(int &x, int y)
{if (x > y)x = y;
}
inline void chkmax(int &x, int y)
{if (x < y)x = y;
}
using ld = long double;
inline void chkmax(ld &x, ld y)
{if (x < y)x = y;
}int addmod(int a, int b)
{a += b;if (a >= mod)a -= mod;return a;
}
int submod(int a, int b)
{a -= b;if (a < 0)a += mod;return a;
}
int mulmod(int a, int b) { return (int)((i64)a * b % mod); }const int N = 1000010;
int n, q, top;
int a[N], rep[N], diff[N];inline void dfs(int x, int y)
{if (!x)return;int l = 1, r = top, best = top + 1;while (l <= r){int mid = l + r >> 1;if (a[mid] > x)best = mid, r = mid - 1;elsel = mid + 1;}--best;if (!best)diff[1] += y, diff[x + 1] -= y;else{rep[best] += x / a[best] * y;dfs(x % a[best], y);}
}signed main()
{cin.tie(0)->sync_with_stdio(false);cout << fixed << setprecision(15);cin >> n >> q;a[top = 1] = n;for (int i = 1; i <= q; ++i){int x;cin >> x;while (top && a[top] >= x)--top;a[++top] = x;}rep[top] = 1;for (int i = top - 1; i; --i){rep[i] += a[i + 1] / a[i] * rep[i + 1];dfs(a[i + 1] % a[i], rep[i + 1]);}diff[1] += rep[1];diff[a[1] + 1] -= rep[1];for (int i = 1; i <= n; ++i)cout << (diff[i] += diff[i - 1]) << '\n';return 0;
}
http://www.jsqmd.com/news/326974/

相关文章:

  • 【题解】P3641 [APIO2016] 最大差分
  • 【题解】P5955 [POI 2018] Pionek
  • 五个值得关注的Python新库
  • 中医执医机构选择:我们应该选哪个课程好?
  • 【题解】P14303 [GCJ 2011 Finals] Runs 加强版
  • 【题解】SP3912 MTREECOL - Color a tree
  • 【题解】P10832 [COTS 2023] 传 Mapa
  • Agent设计模式学习(基于langchain4j实现)(9) - 人机协同
  • C++与Java性能对比
  • 为什么Python依然是初学者最好的选择?
  • 更优雅的测试:Pytest框架入门
  • 【kali显示界面太小?一步教你解决】
  • Python深度学习入门:TensorFlow 2.0/Keras实战
  • 【题解】CF946E Largest Beautiful Number
  • 自定义内存布局控制
  • 嵌入式LinuxC++开发
  • 【题解】P14224 [ICPC 2024 Kunming I] 子数组
  • 自定义操作符重载指南
  • Python游戏中的碰撞检测实现
  • 图标提取神器!一键提取软件安装包中的图标
  • 图片画质增强神器!模糊照片秒变高清
  • 代码质量卫士:使用Pylint和Flake8
  • C++中的策略模式变体
  • Python Web爬虫入门:使用Requests和BeautifulSoup
  • 工具、测试与部署
  • 自动化你的日常工作:一个Python脚本的诞生
  • 构建一个桌面版的天气预报应用
  • 【题解】P7315 [COCI 2018/2019 #3] Sajam
  • 使用Kivy开发跨平台的移动应用
  • 分布式系统C++实现