Official
K - Gcd of Sum Editorial by kaage
累積和を取った数列 \(S\) を考えます。つまり、
\[S_i = \sum_{j=1}^i A_j\]
とします。このとき、約数が \(D\) となるような \(K\) 個への切り分け方が存在する必要十分条件は、\(S_N\equiv 0 \pmod D\) かつ \(S_i\equiv 0 \pmod D\) となる \(1\leq i\leq N\) が \(K\) 個以上存在することです。 これを使うと、\(D\) について \(O(N)\) で切り分け方が存在する最小の \(K\) を見つけることができるので、ありうる \(D\) を全探索すればよいです。
\(S_N\) の最大値は高々 \(9\cdot 10^4\) 程度なので \(S_N\) 以下の \(D\) を全探索しても C++ などの高速な言語なら間に合いますし、\(S_N\equiv 0\pmod D\) を使えばもっと計算量を落とすことができます。(\(O(N\sqrt{sum(A)})\) 程度)
#include <iostream>
#define rep(i, n) for (int i = 0; i < int(n); i++)
#define REP(i, n) for (int i = 1; i <= int(n); i++)
int N, A[310], ans[310];
int main() {
std::cin >> N;
rep(i, N) {
std::cin >> A[i];
if (i) A[i] += A[i - 1];
}
REP(i, 90000) {
if (A[N - 1] % i) continue;
int cnt = 0;
rep(j, N) {
if (A[j] % i == 0) cnt++;
}
REP(j, cnt) ans[j] = i;
}
REP(i, N) std::cout << ans[i] << std::endl;
return 0;
}
posted:
last update: