[AGC063C] Add Mod Operations 题解

Description

给定两个长度为 NN 的非负整数序列 A,BA,B。你需要通过 00NN 次以下的操作,使 AA 变成 BB(如果不行,报告无解;否则给出相应构造方案,注意你并不需要最小化操作次数):

  • 选择两个整数 x,y (0x<y1018)x,y\ (0\le x<y\le 10^{18}),对于所有 1iN1\le i\le N,使 Ai(Ai+x)modyA_i\leftarrow(A_i+x)\bmod y

Solution

容易发现无解的条件是存在 i,ji,j,满足 ai=aj,bibja_i=a_j,b_i\neq b_j

先按照 AA 的大小对数组进行排序,考虑此时 BB 递增时怎么做。

我们想要通过取模让最终的数组可以自由控制。注意到先操作小的再操作大的会对后面的产生影响,这是我们不想看到的,所以倒着做。

具体的,从大到小枚举 ii,每次做 (xi,ai+xi)(x_i,a_i+x_i) 操作,可以让当前最大的清零。做完一轮后 ai=j=1i1xja_i=\sum_{j=1}^{i-1}{x_j},通过最终的数组解出 xx 再做一遍 (b1,+)(b_1,+\infty) 操作即可做到 n+1n+1 次。

考虑优化。注意到最后一次操作是没有意义的,因为只做前 n1n-1 次操作,数组是:

x2+x3++xn,0,x2,x2+x3,,x2+x3++xn1x_2+x_3+\ldots+x_n,0,x_2,x_2+x_3,\ldots,x_2+x_3+\ldots+x_{n-1}

显然同样可以通过 bb 数组解出 xx

对于 bb 不递增的情况可以让 bibi+×(i1)b_i\leftarrow b_i+\infty\times (i-1)

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

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 1e3 + 5, kInf = 1e12;

int n;
int a[kMaxN], _a[kMaxN], b[kMaxN], x[kMaxN];
std::vector<std::pair<int, int>> res;

void work(int x, int y) {
if (!y) return;
x = (x % y + y) % y;
res.emplace_back(x, y);
// std::cerr << "fuck " << x << ' ' << y << '\n';
for(int i = 1; i <= n; ++i) _a[i] = (_a[i] + x) % y;
}

void dickdreamer() {
std::cin >> n;
std::vector<std::pair<int, int>> vec(n);
for (auto &[x, y] : vec) std::cin >> x;
for (auto &[x, y] : vec) std::cin >> y;
std::sort(vec.begin(), vec.end());
for (int i = 1; i <= n; ++i)
a[i] = _a[i] = vec[i - 1].first, b[i] = vec[i - 1].second;

for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
if (a[i] == a[j] && b[i] != b[j])
return void(std::cout << "No\n");
if (n == 1) {
std::cout << "Yes\n1\n" << (b[1] - a[1] + kInf) % kInf << ' ' << kInf << '\n';
return;
}
b[1] += (n - 1) * kInf;
for (int i = 2; i <= n; ++i) b[i] += (i - 2) * kInf;
// for (int i = 1; i <= n; ++i) std::cerr << a[i] << ' ';
// std::cerr << '\n';
// for (int i = 1; i <= n; ++i) std::cerr << b[i] << ' ';
// std::cerr << '\n';
x[n] = b[1] - a[1] - b[n];
for (int i = n; i > 2; --i) x[i - 1] = b[i] - b[i - 1];
// for (int i = 2; i <= n; ++i) std::cerr << x[i] << ' ';
// std::cerr << '\n';
int sum = 0;
for (int i = n; i >= 2; --i) {
work(x[i], a[i] + sum + x[i]);
sum += x[i];
}
work(b[2], kInf);
// for (int i = 1; i <= n; ++i) std::cerr << _a[i] << ' ';
// std::cerr << '\n';
std::cout << "Yes\n";
std::cout << (int)res.size() << '\n';
for (auto [x, y] : res) std::cout << x << ' ' << y << '\n';
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
// std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

[AGC063C] Add Mod Operations 题解
https://sobaliuziao.github.io/2024/10/08/post/6b8dc34f.html
作者
Egg_laying_master
发布于
2024年10月8日
许可协议