title: 牛客练习赛120A-C
date: 2024-01-13 19:41:08
tags: vp
categories: 比赛
A.抽奖黑幕
题目大意
给出一个序列,已经确定了 n − 1 n - 1 n−1 个元素,求能够使序列去除一个最大值和一个最小值之后的总和最大的最小值正整数 a n a_n an
解题思路
观察发现,分两种情况,第一种是整个序列元素大小是一样的,这个时候我们取 1 1 1 是最优解;第二种情况是,不完全一样,这个时候就选择最大值即可,保留一个最大值,最小值和原来的最大值就去除,最优
代码实现
void solve()
{
int n; cin >> n;
vector<int> a(n);
for (int i = 0; i < n - 1; i++) cin >> a[i];
int flag = 0, x = 1;
for (int i = 1; i < n - 1; i++) {
if (a[i - 1] != a[i]) {
flag = 1;
break;
}
}
if (flag) {
for (int i = 0; i < n - 1; i++) x = max(x, a[i]);
}
cout << x << endl;
}
B.生成函数
题目大意
三种无限的砝码一个一个物品 m m m,问能否通过放置砝码使得天平平衡。
解题思路
砝码左右都可以加,只要最终保证天平平衡即可,那么就需要保证,这几个数的最大公约数能够被物品 m m m 整除
代码实现
void solve()
{
int a, b, c, m;
cin >> a >> b >> c >> m;
int aa = abs(a - b), bb = abs(b - c);
int GCD = gcd(aa,bb );
GCD = gcd(a, GCD);
GCD = gcd(b, GCD);
GCD = gcd(c, GCD);
if (m % GCD) cout << "NO" << endl;
else cout << "YES" << endl;
}
C.选择交换
题目大意
给出一个序列,交换位置使得序列满足
a 1 + a n = a 2 + a n − 1 … … = a n 2 + a n + 1 − n 2 a_1 + a_n = a_2 + a_{n - 1} …… = a_{\frac{n}{2}} + a_{n + 1 - \frac{n}{2}} a1+an=a2+an−1……=a2n+an+1−2n
解题思路
将序列的值和下标绑定,动态维护交换序列。找出序列大小的平衡值,如果奇数序列中间的元素不满足平衡值,则是不合法的序列,同时当循环中发现对应的元素不满足平衡值,也是不合法的序列。剩余情况均合法,则动态维护序列,求得下标交换过程
代码实现
PII a[N];
bool cmp(PII A,PII B){
return A.fi < B.fi;
}
void solve()
{
int n; cin >> n;
for (int i = 1; i <= n; i++) {
int v; cin >> v;
a[i] = { v,i };
}
sort(a + 1, a + n + 1,cmp);
ll var = a[1].fi + a[n].fi;
//判断有没有解
if (n % 2) {
if (a[n / 2 + 1].fi * 2 != var) {
cout << "NO" << endl;
return;
}
}
for (int i = 1; i <= n; i++) {
if (a[i].fi + a[n - i + 1].fi != var) {
cout << "NO" << endl;
return;
}
}
//合理的
cout << "YES" << endl;
vector<PII> vec;
for (int i = 1; i <= n; i++) {
while (a[i].se != i) {
vec.pb({ a[i].se,i });
swap(a[i].se,a[a[i].se].se);
}
}
cout << vec.size() << endl;
reverse(vec.begin(),vec.end());
for (auto [x, y] : vec) {
cout << x << ' ' << y << endl;
}
}