Subarray Sum Divisibility (ABC 419)

First Post:

Last Update:

Word Count:
355

Read Time:
1 min

Page View: loading...

硬控 10min+,死因是想问题的时候老是忘记我只需要做

数据范围很重要啊!

给你一个长度为 的整数序列

你的目标是重复执行以下操作,使 的每个长度为 连续子数组的和都是 的倍数。

  • 选择 这样的整数 ,并将 的值增加

求达到目标所需的最小运算次数。


首先应该观察到最终每相隔 的位置上的数模 同余,即位置模 同余的数是“绑定”的。

因此只需要确认任意一个长为 的连续子数组的值。

枚举每一组模 同余的位置,同时枚举 内每一个整数 ,确认这些位置所有的数变换到与 同余的代价。

最后做一个类似背包的东西,最小化总代价。

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
#include <bits/stdc++.h>
using namespace std;

int main() {
cin.tie(nullptr)->sync_with_stdio(false);
size_t n, m, l;
cin >> n >> m >> l;
vector<vector<int32_t>> cost(l, vector<int32_t>(m));
for (size_t i = 0; i < n; ++i) {
int32_t x;
cin >> x;
for (size_t j = 0; j < m; ++j)
cost[i % l][j] += (j - x + m) % m;
}
vector<int32_t> F(m, 0x3f3f3f3f);
F[0] = 0;
for (const auto &cc : cost) {
vector<int32_t> G(m, 0x3f3f3f3f);
for (size_t i = 0; i < m; ++i)
for (size_t j = 0; j < m; ++j)
G[(i + j) % m] = min(G[(i + j) % m], F[i] + cc[j]);
F = move(G);
}
cout << F[0] << '\n';
return 0;
}