E - Sum of Min of Mod of Linear 解説 by evima
Hints
Hint 1
Consider the case $N=1$. In other words, try to find $\displaystyle \sum_{k=0}^{K-1} \lbrace\left(Ck+A_1\right)\ \mathrm{mod}\ M\rbrace$.Answer to Hint 1
By using the expression $\displaystyle \left(Ck+A_1\right)\ \mathrm{mod}\ M=Ck+A_1-M\left\lfloor\frac{Ck+A_1}M\right\rfloor$, you can reduce the problem to the floor_sum algorithm.Hint 2
The answer does not depend on the order of $A$. Therefore, consider the case where $A$ has no duplicates and is sorted.Hint 3
Consider how much less is the original answer compared to $\displaystyle \sum_{k=0}^{K-1} \lbrace\left(Ck+A_1\right)\ \mathrm{mod}\ M\rbrace$.Hint 4
For the situation in Hint 3, consider finding the contribution of each $i$ $(2\le i\le N)$.Editorial
As a prerequisite, you need the floor_sum algorithm. This algorithm calculates \(\displaystyle f(n,m,a,b)=\sum_{i=0}^{n-1}\left\lfloor\frac{ai+b}m\right\rfloor\) in \(O(\log m)\) time. Please read the explanation in the linked article for more details.
Let’s assume that \(A\) has been sorted and duplicates removed so that \(A_1 < A_2 < ... < A_N\) holds.
Fix \(j\), and let \(S_j\) be the set of \(0\le k < K\) such that \(\displaystyle \left\{(Ck+A_j)\ \text{mod}\ M\right\}=\min_{1\le i\le N}\left\{(Ck+A_i)\ \text{mod}\ M\right\}\). If \(j\geq 2\), the condition for \(k\in S_j\) can be rephrased as \(\left\{(Ck+A_{j-1})\ \text{mod}\ M \right\} > \left\{(Ck+A_j)\ \text{mod}\ M \right\}\), and further as \(\displaystyle \left\lfloor\frac{Ck+A_{j}}{M} \right\rfloor-\left\lfloor\frac{Ck+A_{j-1}}{M} \right\rfloor=1\). Since \(\displaystyle \left\lfloor\frac{Ck+A_{j}}{M} \right\rfloor-\left\lfloor\frac{Ck+A_{j-1}}{M} \right\rfloor\) can only be \(0\) or \(1\), we have \(\displaystyle |S_j|=\sum_{k=0}^{K-1}\left(\left\lfloor\frac{Ck+A_{j}}{M} \right\rfloor-\left\lfloor\frac{Ck+A_{j-1}}{M} \right\rfloor\right)\).
Therefore,
\[ \begin{aligned} &\phantom{=}\sum_{k\in S_j}\min_{1\le i\le N}\left\{(Ck+A_i)\ \text{mod}\ M \right\}-\sum_{k \in S_j} \left\{(Ck+A_1)\ \text{mod}\ M \right\}\\ &=\sum_{k \in S_j}\left(\left\{(Ck+A_j)\ \text{mod}\ M \right\} - \left\{(Ck+A_1)\ \text{mod}\ M \right\}\right)\\ &=\sum_{k \in S_j} (A_j-A_1-M)\\ &=-(M+A_1-A_j)|S_j| \end{aligned} \]
Meanwhile, for \(j=1\), we have
\[\sum_{k\in S_j}\min_{1\le i\le N}\left\{(Ck+A_i)\ \text{mod}\ M \right\}-\sum_{k \in S_j} \left\{(Ck+A_1)\ \text{mod}\ M \right\}=0\]
Thus, the answer is
\[ \begin{aligned} &\phantom{=}\sum_{k=0}^{K-1}\min_{1\le i\le N}\left\{(Ck+A_i)\ \text{mod}\ M \right\}\\ &=\sum_{j=1}^N\sum_{k\in S_j}\left\{(Ck+A_j)\ \text{mod}\ M \right\}\\ &=\sum_{j=1}^N\sum_{k \in S_j} \left\{(Ck+A_1)\ \text{mod}\ M \right\} -\sum_{j=2}^N(M+A_1-A_j)|S_j|\\ &=\sum_{k=0}^{K-1} \left\{(Ck+A_1)\ \text{mod}\ M \right\}-\sum_{j=2}^N (M+A_1-A_j)|S_j| \end{aligned} \]
\(\displaystyle \sum_{k=0}^{K-1} \left\{(Ck+A_1)\ \text{mod}\ M \right\}=\sum_{k=0}^{K-1}\left(Ck+A_1-M\left\lfloor\frac{Ck+A_1}M \right\rfloor\right)\) and \(|S_j|\) can both be calculated quickly using the floor_sum algorithm.
Now, the problem is solved. The complexity is \(O(N(\log N+\log M))\), with the bottlenecks being the sorting of \(A\) and the calculation of floor_sum.
Be careful with overflow during implementation. You can avoid this issue by using multi-precision integers, 128-bit integers, or by using a modint with two different primes (e.g., \(10^9+7\) and \(10^9+9\)) and reconstructing the result using CRT. Alternatively, you can use a type like C++’s unsigned long long, which guarantees that the correct value modulo \(2^{64}\) is returned even in case of overflow. The AtCoder Library’s floor_sum uses unsigned long long and guarantees the correct answer modulo \(2^{64}\).
Sample Implementation (Python3)
from atcoder.math import floor_sum
n, m, c, k = map(int, input().split())
a = sorted(list(set(map(int, input().split()))))
n = len(a)
fl = [floor_sum(k, m, c, a[i]) for i in range(n)]
ans = c * k * (k - 1) // 2 + k * a[0] - m * fl[0]
for i in range(1, n):
ans -= (m + a[0] - a[i]) * (fl[i] - fl[i - 1])
print(ans)
#include <bits/stdc++.h>
#include <atcoder/math>
using namespace std;
#define ull unsigned long long
int main() {
ull n, m, c, k;
cin >> n >> m >> c >> k;
vector<ull> a(n);
for (ull& i : a) cin >> i;
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
n = a.size();
vector<ull> fl(n);
for (int i = 0; i < n; i++) {
fl[i] = atcoder::floor_sum(k, m, c, a[i]);
}
ull ans = k * (k - 1) / 2 * c + k * a[0] - m * fl[0];
for (int i = 1; i < n; i++) {
ans -= (m + a[0] - a[i]) * (fl[i] - fl[i - 1]);
}
cout << ans << endl;
}
投稿日時:
最終更新: