比赛链接:
https://atcoder.jp/contests/arc137/tasks
A - Coprime Pair
题目大意:
给了 \(l\) 和 \(r\),求出 \(x\) 和 \(y\),在满足 \(l <= x < y <= r\),且 \(gcd(x, y) = 1\) 的情况下,使得 \(y - x\) 最大。
思路:
因为最多 1500 个数中就会有一个质数,所以直接暴力搜就可以了。
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
LL l, r;
int main(){
cin >> l >> r;
for (LL i = r - l; i >= 0; -- i) //枚举长度
for (LL j = l; j + i <= r; ++ j) //枚举起点
if (__gcd(j, j + i) == 1){
cout << i << "\n";
return 0;
}
return 0;
}
B - Count 1's
题目大意:
给定了一个只包含 0 和 1 的序列,现在可以翻转一个连续区间的值,即将这个区间所有 0 变成 1,1 变成 0,问 1 的数量有多少种可能。
思路:
要统计出改变某一个区间最多能减少或增减多少个 1,就是求最大子段和,不过要求两次,答案就是 1 加上增加和减少的最大值就可以了。
代码:
#include <bits/stdc++.h>
using namespace std;
int n, s, ans1, ans2;
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin >> n;
vector <int> a(n);
for (int i = 0; i < n; ++ i){
cin >> a[i];
if (!a[i]) a[i] = -1;
s = max(s + a[i], a[i]);
ans1 = max(ans1, s);
}
s = 0;
for (int i = 0; i < n; ++ i){
a[i] = -a[i];
s = max(s + a[i], a[i]);
ans2 = max(ans2, s);
}
cout << ans1 + ans2 + 1 << "\n";
return 0;
}
C - Distinct Numbers
题目大意:
\(Alice\) 和 \(Bob\) 玩游戏,有一个序列 \(A\),没人操作一次,\(Alice\) 先手操作,每次可以选择序列中最大的一个数,将其改为任意一个比自身小的非负数,但是序列中不能改为序列中已有的数,当有一个人不能操作之后,则另一人获胜,两人都足够聪明,都采取最优策略。
思路:
记最大的元素记为 \(a\),次大的记为 \(b\)。
当只有一个元素可以移动,其它都已经在前面的时候,先手必胜,即满足 \(b + 2 <= a\),如果 \(b + 1 = a\) 说明 \(a\) 也不能移动了。
还有两个及以上的数要移动时,要看最大的两个数之间的关系。如果刚开始就是 \(b + 1 = a\) ,那么每次的最优决策就是将 \(a\) 移到 \(b - 1\) 的位置,因为否则的话就会让对手处在 \(b + 2 <= a\) 的状态,则自己就会输。
每个人都是最优,即每次都让 \(a = b - 1\),那这时就要看移多少次才会移动到不能移的时候,判断一下 \(a\) 和 \(n - 1\) 的奇偶性就可以了。
代码:
#include <bits/stdc++.h>
using namespace std;
#define all(x) x.begin(), x.end()
int n;
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin >> n;
vector <int> a(n);
for (int i = 0; i < n; ++ i)
cin >> a[i];
sort(all(a));
if (a[n - 2] + 2 <= a[n - 1]) cout << "Alice\n";
else{
int res = ( a[n - 1] - (n - 1) ) & 1;
if (res) cout << "Alice\n";
else cout << "Bob\n";
}
return 0;
}