Codeforces Round 1045 (Div. 2) (A ~ C)
A. Painting With Two Colors
思维
题意:
一个长度为\(n\)的数组,先把一段长度为\(a\)的子数组染为红色,再把一段长度为\(b\)的子数组染为蓝色,蓝色会覆盖红色。求能不能使得数组是回文。
思路:
最后要求数组是回文的那么每次都需要对称的去放,分成以下两种情况判断一下即可:
- \(a\)和\(b\)与\(n\)奇偶性都相同
- \(a\)与\(n\)奇偶性不同,这时需要用蓝色去覆盖使其对称,所以\(b\) > \(a\)并且\(b\)与\(n\)奇偶性相同
不满足以上情况之一的都是不对称的
代码:
void solve()
{
int n, a, b;
std::cin >> n >> a >> b;
if (b % 2 == n % 2 and (b > a or a % 2 == n % 2)) std::cout << "YES\n";
else std::cout << "NO\n";
}
B. Add 0 or K
数论
题意:
给定一个数组以及一个\(k\),最多可以对数组做不超过\(k\)次操作,每次操作可以给数组每个数加上\(0\)或者\(k\),要求通过若干次操作使数组的\(gcd\) > \(1\),输出这个数组
思路:
首先定义这样的一个数组\(gcd\) = \(p\),它符合\(gcd(p, k) = 1\)
可以证明在\(k\)次操作以内通过对数组元素若干次加\(k\),使其可以被\(p\)整除
证明:
如何找到这样的\(p\):
代码:
void solve()
{
int n, k, p = 2;
cin >> n >> k;
while(__gcd(p,k) > 1) p ++;
for(int i = 1; i <= n; i ++)
{
int x;
cin >> x;
while(x % p > 0) x += k;
cout << x << " \n"[i == n];
}
}
C. Even Larger
贪心 思维
题意:
给定一个数组,每次操作可以将一个数组元素的值减一,问最少需要多少次操作可以使所有长度大于等于\(2\)的子数组满足偶数索引元素之和 >= 奇数索引元素之和(这里索引的奇偶是相对原数组来说的)
思路:
不难发现让\(a_i >= a_{i - 1} + a_{i + 1}\)即可,这里的\(i\)都是偶数索引,如果某一索引不符合条件的话优先减小\(a_{i + 1}\)的值,这样对后面的元素可能也是有贡献的
代码:
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
for(int i = 1; i <= n; i ++) cin >> a[i];
int cnt = 0;
for(int i = 2; i <= n; i += 2)
{
int x = a[i - 1];
if(i + 1 <= n) x += a[i + 1];
int t = max(x - a[i], 0LL);
cnt += t;
if(i + 1 <= n) a[i + 1] -= min(t, a[i + 1]);
}
cout << cnt << '\n';
}