CodeForces 1909D Split Plus K

洛谷传送门

CF 传送门

设最后每个数都相等时为 \(t\)。那么一次操作变成了合并两个数 \(x, y\),再增加 \(x + y - k\)。于是每个 \(a_i\) 可以被表示成 \(b_i t - (b_i - 1)k\) 的形式,化简得 \(a_i - k = b_i (t - k)\)

因为 \(t - k\) 对于每个 \(i\) 都相同,又因为我们的目标是最小化 \(\sum\limits_{i = 1}^n b_i\),所以 \(t - k\)\(\gcd\limits_{i = 1}^n (a_i - k)\) 最优。

注意所有 \(a_i - k\) 同号才合法,以及特判掉初始 \(a_i\) 全部相同的情况后不能出现 \(a_i = k\)

code
// Problem: D. Split Plus K
// Contest: Codeforces - Pinely Round 3 (Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1909/problem/D
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

ll n, m, a[maxn];

void solve() {
	scanf("%lld%lld", &n, &m);
	ll s = 0, g = 0;
	bool fl = 1;
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		s += a[i];
		g = __gcd(g, abs(a[i] - m));
		fl &= (a[i] == a[1]);
	}
	if (fl) {
		puts("0");
		return;
	}
	ll ans = 0;
	int x = 0;
	for (int i = 1; i <= n; ++i) {
		if (a[i] == m) {
			puts("-1");
			return;
		}
		if (a[i] > m) {
			x |= 1;
		} else {
			x |= 2;
		}
		ans += abs(a[i] - m) / g;
	}
	printf("%lld\n", x == 3 ? -1LL : ans - n);
}

int main() {
	int T = 1;
	scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2023-12-24 12:16  zltzlt  阅读(57)  评论(0编辑  收藏  举报