C - Candy Tribulation Editorial
by
sheyasutaka
考察
\(A\) を昇順に並べ替えて \(A_1 \leq A_2 \leq \cdots A_N\) としても答えは変わらないので,以下ではこれが満たされるものとします.
子供 \(i\) に配る大きな飴の個数を \(x_i\) 個とおきます.このとき,\(0 \leq x_i \leq A_i\) です.
子供 \(1,k\) について飴の総重量が等しいという条件は
\[(A_1 - x_1) X + x_1 Y = (A_k - x_k) X + x_k Y\]
と書けて,これを変形すると
\[x_k = x_1 - \frac{(A_k - A_1)X}{Y-X}\]
となります.これは,\(x_1 - x_k\) が決まった値 \(\displaystyle \frac{(A_k - A_1)X}{Y-X}\) になることを表しています.以下ではこれを \(D_k\) とおきます.\(A_1 \leq A_k\) より \(D_k \geq 0\) です.
各 \(k\) について,以下の必要条件が導けます.
- \(x_1, x_2, \dots, x_N\) は整数なので,その差である \(D_k\) も整数である必要があります.
- \(x_k \geq 0\) および \(x_1 \leq A_1\) より,\(D_k\) は \(A_1\) 以下である必要があります.
逆に,これらの条件が満たされるならば,\(x_k = A_1 - D_k\) とすることで問題文中の条件を満たすことができます.\(x_k = x_1 - D_k\) および \(x_1 \leq A_1\) から,これは \(x_k\) のとり得る最大値でもあるので,これらの和が答えとなります.
実装例 (C++)
\(\displaystyle x_k = A_1 - \frac{(A_k - A_1)X}{Y-X}\) は \(\displaystyle x_k = A_k - \frac{(A_k - A_1)Y}{Y-X}\) と表すこともでき,以下の実装例ではこちらの式で計算しています.
#include <iostream>
using std::cin;
using std::cout;
using std::min;
using std::max;
#include <vector>
using std::vector;
typedef long long int ll;
ll n, x, y;
vector<ll> a;
ll solve () {
ll mina = a[0];
for (ll i = 0; i < n; i++) {
mina = min(mina, a[i]);
}
ll sum = 0;
ll w = mina * y;
for (ll i = 0; i < n; i++) {
ll vs = (a[i] - mina) * y;
ll vt = (y - x);
if (vs % vt != 0) {
return -1;
}
ll minor = vs / vt;
if (minor > a[i]) {
return -1;
}
sum += (a[i] - minor);
}
return sum;
}
int main (void) {
// input
cin >> n >> x >> y;
a.resize(n);
for (ll i = 0; i < n; i++) {
cin >> a[i];
}
ll ans = solve();
cout << ans << "\n";
return 0;
}
posted:
last update:
