1 条题解
-
0
自动搬运
来自洛谷,原作者为

Alex_Wei
**搬运于
2025-08-24 21:48:52,当前版本为作者最后更新于2022-02-05 10:56:08,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
好题!先求和,再调整。
由于题目给出的 是齐肯多夫表示法,所以简单地对应位求和 后,。
考虑从高往低位调整,即依次保证长为 的前缀,长为 的前缀 …… 直到整个数都满足齐肯多夫表示法,类似 数学归纳法。因为从低到高涉及进位,很麻烦。下称满足齐肯多夫表示法为 合法。
我们发现最棘手的是 ,别的都好办。由于 ,考虑一次操作 表示令 ,,。此时可能导致低位 的出现,但是问题不大,因为我们只关心 及其高位。
我们的目标是 尽可能消掉 ,自然不希望已经处理好的高位重新出现 。由于 及其高位合法,所以不会出现连续的两个 。因此,若 且 , 会令 变成 。
不妨先执行进位操作,即 ,,。由于 一定等于 ,所以进位后等于 。同时,若 ,那么继续进位到 。称从 开始不断进位的过程为 ,其代码如下:
void flush(int p) {while(z[p] && z[p + 1]) z[p + 2]++, z[p]--, z[p + 1]--, p += 2;}注意,当 及其高位均合法时,操作才不会出错,即操作结束后 及其高位仍合法。容易证明这一点。否则可能出现数码 。如当 时,这样的进位导致 ,破坏了齐肯多夫表示法,但若 及其高位合法,则不会出现 的情况。
执行完 或 次进位操作后,,因此若 ,再执行 仅会将 变为 ,且由于 ,故现在所有 及其高位均有 ,但 及其高位不一定合法,因为可能 。由于此时 及其高位合法,所以先 ,再 即可保证对于得到的结果, 及其高位合法。
啰里啰嗦这么一大堆,只是为了严谨证明以下做法的正确性:
- 从高到低考虑每一位 。保证 及其高位合法。
- 首先 。
- 若 ,则依次执行 ,,。
- 此时 及其高位合法。
特殊情况: 令 ,,。 令 ,。不难发现我们对高位的影响最多仅是令 加 ,和普通的 是一样的,故特殊情况也一定合法。
时间复杂度分析:考虑 ,每次进位均会让 减少 ,而
op不改变 ,故flush的总复杂度均摊为 ,即总时间复杂度线性。#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 5; int n, m, x[N]; void flush(int p) {while(x[p] && x[p + 1]) x[p + 2]++, x[p]--, x[p + 1]--, p += 2;} int main() { cin >> n; for(int i = 1; i <= n; i++) scanf("%d", &x[i]); cin >> m; for(int i = 1, y; i <= m; i++) scanf("%d", &y), x[i] += y; if(m > n) n = m; for(int i = n; i; i--) { flush(i); if(x[i] >= 2) { if(i >= 2) x[i] -= 2, x[max(1, i - 2)]++, x[i + 1]++; else x[i + 1]++, x[i] -= 2; flush(i + 1), flush(i); } } for(int i = n + 2; i; i--) if(x[i]) {cout << (n = i) << " "; break;} for(int i = 1; i <= n; i++) putchar(x[i] + '0'), putchar(' '); return 0; }
- 1
信息
- ID
- 2501
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者