Official

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: