Codeforces Round #808 (Div. 2)
作者:互联网
Codeforces Round #808 (Div. 2)
传送门:https://codeforces.com/contest/1708
错过了,第二天vp的,只写出了AB就卡C了,竟然看不出是贪心555
A. Difference Operations
题意:给一个数组,由如下操作,问能不能使得\(a_2\) 到\(a_n\) 全为0
操作是选择一个i,使得\(a_i=a_i-a_{i-1}\) 。
解:显然\(a_2\) 是\(a_1\)的倍数,才可能被剪成0,同理\(a_3 是a_2 被减过程中某个数字的倍数\)
那么意味着所有数字都得是\(a_1\)的倍数,并且中间不可以被0隔断。
#include <bits/stdc++.h>
signed main() {
int t;
std::cin >> t;
while (t--) {
int n;
std::cin >> n;
int a[110] = {0};
for (int i = 1; i <= n; i++)
std::cin >> a[i];
int k = a[1];
bool f = 1;
for (int i = 2; i <= n; i++) {
if (k == 0 && a[i] != 0 || a[i] % k != 0)
f = 0;
if (a[i - 1] == 0 && a[i])
f = 0;
}
if (f)
std::cout << "YES" << std::endl;
else
std::cout << "NO" << std::endl;
}
}
B. Difference of GCDs
题意:构造一个长度为n的数组,满足所有数字都在区间[l,r]内。
并且所有\(gcd(i,a_i )\) 的值互不相同。i
解法:因为\(gcd(i,a_i )<=i\) 又要互不相同,那么就必须$gcd(i,a_i )==i $ 也就是说\(a_i 必须是i的倍数\) 然后就在[l,r]里随便找个倍数就行了。找不到就输出NO
#include <bits/stdc++.h>
#define int long long
const int N = 1e5 + 10;
int a[N];
signed main() {
std::ios::sync_with_stdio(false);
int t;
std::cin >> t;
while (t--) {
int n, l, r;
std::cin >> n >> l >> r;
bool f = 1;
for (int i = 1; i <= n; i++) {
a[i] = 0;
for (int j = (l - 1) / i * i + i; j <= r; j += i) {
if (j >= a[i]) {
a[i] = j;
break;
}
}
if (!a[i])
f = 0;
}
if (!f) {
std::cout << "NO" << std::endl;
continue;
} else {
std::cout << "YES" << std::endl;
for (int i = 1; i <= n; i++)
std::cout << a[i] << " \n"[i == n];
}
}
}
C. Doremy's IQ
题意:有n天,第i天有考试i,难度为\(a_i\) 有起始智商q,当q<=0时她无法继续参加考试。
如果参加的考试\(a_i>q\)那么q--。
问如何选择哪几天考试能考的次数最多。答案以01串输出。
思路:贪心地想,掉智商肯定是越迟掉越好,如果在i天选择了掉智商的考试,那么之后也要义无反顾地考下去。于是,我们可以直接二分从哪天开始掉智商并能考完后面的全部考试的。求出i最小的方案即可输出。
#include <bits/stdc++.h>
#define int long long
const int N = 1e5 + 10;
int a[N];
int ans[N];
int n, q;
std::vector<int> ve;
bool check(int p) {
int qq = q;
for (int i = 1; i < p; i++) {
if (a[i] > qq) {
ans[i] = 0;
} else {
ans[i] = 1;
}
}
for (int i = p; i <= n; i++) {
ans[i] = 1;
if (a[i] > qq)
qq--;
}
return qq >= 0;
}
signed main() {
std::ios::sync_with_stdio(false);
int t;
std::cin >> t;
while (t--) {
std::cin >> n >> q;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
int l = 0, r = n;
while (l < r) {
int m = (l + r) >> 1;
if (check(m)) {
r = m;
} else
l = m + 1;
}
check(l);
for (int i = 1; i <= n; i++) {
std::cout << ans[i];
}
std::cout << "\n";
}
}
D. Difference Array
题意:给一个数组。让你把它变成它的差分数组,然后升序,继续变成差分数组...
直到最终只剩一个数字,输出这个数字。
思路:直接模拟肯定不行,但是发现,随着差分操作,一定会出现大量的0,而0和0的差分还是0,那么我们就可以直接把所有的0拿出来,每次操作减一,然后算上新生成的。其他过程就暴力模拟就好了。
#include <bits/stdc++.h>
#define int long long
const int N = 1e5 + 10;
int a[N];
signed main() {
std::ios::sync_with_stdio(false);
int t;
std::cin >> t;
while (t--) {
int n;
std::cin >> n;
std::vector<int> ve[2];
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
ve[0].push_back(a[i]);
}
int now = 0;
int cost0 = 0;
while (ve[now].size() >= 2) {
std::sort(ve[now].begin(), ve[now].end());
ve[now ^ 1].clear();
if (cost0) {
ve[now ^ 1].push_back(ve[now][0]);
cost0--;
}
for (int i = 0; i < ve[now].size() - 1; i++) {
int k = ve[now][i + 1] - ve[now][i];
if (k == 0) {
cost0++;
} else
ve[now ^ 1].push_back(k);
}
now ^= 1;
}
if (ve[now].size() == 0)
std::cout << 0 << "\n";
else if (ve[now].size() == 1) {
std::cout << ve[now][0] << "\n";
} else if (cost0 >= 1) {
std::sort(ve[now].begin(), ve[now].end());
int k1 = ve[now][0], k2 = ve[now][1] - ve[now][0];
std::cout << std::abs(k1 - k2) << "\n";
} else
std::cout << std::abs(ve[now][0] - ve[now][1]) << "\n";
}
}
标签:std,ve,int,Codeforces,cin,--,808,Div,now 来源: https://www.cnblogs.com/wtn135687/p/16489932.html