A:Codeforces 1328A Divisibility Problem 整除+模

Codeforces Round #629 (Div. 3) A~D,F - 图1

Input

  1. 5
  2. 10 4
  3. 13 9
  4. 100 13
  5. 123 456
  6. 92 46

Output

  1. 2
  2. 5
  3. 4
  4. 333
  5. 0

按需取余,和我之前发的文章一样的解法

  1. ll a, b;
  2. void solve() {
  3. cin >> a >> b;
  4. cout << (b - a % b) % b << "\n";
  5. }

B:Codeforces 1328B K-th Beautiful String

Codeforces Round #629 (Div. 3) A~D,F - 图2

Input

  1. 7
  2. 5 1
  3. 5 2
  4. 5 8
  5. 5 10
  6. 3 1
  7. 3 2
  8. 20 100

Output

  1. aaabb
  2. aabab
  3. baaba
  4. bbaaa
  5. abb
  6. bab
  7. aaaaabaaaaabaaaaaaaa

就是找到第 Codeforces Round #629 (Div. 3) A~D,F - 图3 个全排列的字符串

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. int _; for (cin >> _; _--;) {
  4. int n, k; cin >> n >> k;
  5. string s(n, 'a');
  6. for (int i = n - 2; i >= 0; i--) {
  7. if (k <= n - (i + 1)) {
  8. s[i] = 'b', s[n - k] = 'b';
  9. break;
  10. } else k -= n - (i + 1);
  11. }
  12. cout << s << "\n";
  13. }
  14. }

C:Codeforces 1328C Ternary XOR 贪心

Codeforces Round #629 (Div. 3) A~D,F - 图4

Input

  1. 4
  2. 5
  3. 22222
  4. 5
  5. 21211
  6. 1
  7. 2
  8. 9
  9. 220222021

Output

  1. 11111
  2. 11111
  3. 11000
  4. 10211
  5. 1
  6. 1
  7. 110111011
  8. 110111010

题意:

给出一个 Codeforces Round #629 (Div. 3) A~D,F - 图5 的三进制数字,Codeforces Round #629 (Div. 3) A~D,F - 图6 的第一个数字必须是 Codeforces Round #629 (Div. 3) A~D,F - 图7,求出两个数 Codeforces Round #629 (Div. 3) A~D,F - 图8Codeforces Round #629 (Div. 3) A~D,F - 图9 ,使得 Codeforces Round #629 (Div. 3) A~D,F - 图10Codeforces Round #629 (Div. 3) A~D,F - 图11#card=math&code=max%28a%2Cb%29&id=yBplD) 最小。

贪心,要使得最小的话对于 Codeforces Round #629 (Div. 3) A~D,F - 图12 就是两个位置都放置 Codeforces Round #629 (Div. 3) A~D,F - 图13 ,对于 Codeforces Round #629 (Div. 3) A~D,F - 图14 就是两个位置都放置 Codeforces Round #629 (Div. 3) A~D,F - 图15,但是这样肯定不能保证 Codeforces Round #629 (Div. 3) A~D,F - 图16 的最大值最小,所以只要保证第一次出现 Codeforces Round #629 (Div. 3) A~D,F - 图17 的时候分配给第一个,然后后面的都设置为 Codeforces Round #629 (Div. 3) A~D,F - 图18

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. int _; for (cin >> _; _--;) {
  4. ll n; string s, a, b;
  5. cin >> n >> s;
  6. bool f = 0;
  7. //让我们求最小的a,2需要ab平均均摊,但只要1出现了以后直接另所有的都赋给b即可
  8. for (int i = 0; i < s.length(); ++i) {
  9. if (f) a += '0', b += s[i]; //第一个1以后直接另b等于s[i]即可
  10. else if (s[i] == '2') a += '1', b += '1';
  11. else if (s[i] == '1') a += '1', b += '0', f = 1;
  12. else a += '0', b += '0';
  13. }
  14. cout << a << "\n" << b << "\n";
  15. }
  16. }

1328D - Carousel

Codeforces Round #629 (Div. 3) A~D,F - 图19 个木马围成圈,为每个属性为 Codeforces Round #629 (Div. 3) A~D,F - 图20 的木马涂上一种颜色 Codeforces Round #629 (Div. 3) A~D,F - 图21 ,要求任何相邻的属性不同的木马颜色不同,问最少需要多少种颜色,并输出涂色方案(tip:属性相同的木马颜色可以不同也可以相同)

  1. 如果所有木马属性都相同,那么最少要涂一种颜色,需要特判
  2. 属性相同的木马颜色可以不同也可以相同,那么我们可以交替涂1,2,1,2,…如果n为偶数,那么一定满足条件且只需要两种颜色
  3. 如果n为奇数,那么我们希望最后一个数c[n]两边的颜色c[1]和c[n - 1]尽可能相同,这样我们就不用使用第三种颜色,使答案最佳
  4. 我们只要找到第n个数之前的t[i] = t[i - 1] (2 <= i <= n - 1),然后从i开始的每个数与1异或即可(写代码时需要从零开始,才能0,1异或,最后答案加1即可)
  5. .经过步骤4后,如果c[1] == c[n - 1],c[n] = c[1] ^ 1即可
  6. 如果c[1] != c[n - 1](也就是前n - 1个属性都不同,无法通过步骤4使得c[1] == c[n - 1]),且c[n]与相邻两个数c[1]和c[n - 1]都不相同,那么c[n] = 2(最后答案会加1),否则t[n] == t[n - 1] ->c[n] = c[n -1]或者 t[n] == t[1] -> c[n] = c[1]
  1. void solve() {
  2. int n; cin >> n;
  3. vector<int> a(n);
  4. for (int &x : a) cin >> x;
  5. bool same = 1;
  6. for (int i = 0; i < n && same; ++i) if (a[i] != a[0]) same = 0;
  7. if (same) {
  8. cout << "1\n";
  9. for (int i = 0; i < n; ++i) cout << 1 << " \n"[i == n - 1];
  10. return ;
  11. }
  12. if (n % 2 == 0) {
  13. cout << "2\n";
  14. for (int i = 0; i < n; ++i)
  15. cout << (1 + (i & 1)) << " \n"[i == n - 1];
  16. return ;
  17. }
  18. for (int i = 0; i < n; i++) {
  19. if (a[i] == a[(i + 1) % n]) {
  20. cout << 2 << '\n';
  21. for (int j = 0; j < n; j++) {
  22. cout << 1 + (1 & ((j - i - 1 + n) % n)) << " \n"[j == n - 1];
  23. }
  24. return;
  25. }
  26. }
  27. cout << "3\n3 ";
  28. for (int i = 1; i < n; i++)
  29. cout << 1 + (i & 1) << " \n"[i == n - 1];
  30. }

1328F. Make k Equal

题意:把 Codeforces Round #629 (Div. 3) A~D,F - 图22 个数变成 Codeforces Round #629 (Div. 3) A~D,F - 图23 个相同的数,每次可以把 Codeforces Round #629 (Div. 3) A~D,F - 图24 个数里最大的 Codeforces Round #629 (Div. 3) A~D,F - 图25 或最小的 Codeforces Round #629 (Div. 3) A~D,F - 图26 ,问最小改变次数

思路:

我们可以枚举,把 Codeforces Round #629 (Div. 3) A~D,F - 图27 个数变成 Codeforces Round #629 (Div. 3) A~D,F - 图28Codeforces Round #629 (Div. 3) A~D,F - 图29 (这个相同的数一定是数组里的数,因为如果不是,那么改变次数一定会比正常多)

如果相同的数大于 Codeforces Round #629 (Div. 3) A~D,F - 图30 个,那么改变次数为 Codeforces Round #629 (Div. 3) A~D,F - 图31 ,特判掉

有三种情况,一种是只动前面,一种只动后面,还有就是前后都动

因为是改变最大或最小的数,所以我们只有把所有小于 Codeforces Round #629 (Div. 3) A~D,F - 图32 的数变成 Codeforces Round #629 (Div. 3) A~D,F - 图33 (或者大于 Codeforces Round #629 (Div. 3) A~D,F - 图34 的数变成Codeforces Round #629 (Div. 3) A~D,F - 图35 )才能进行下一次的改变

然后接着考虑,在什么情况下可以动前面呢,当然是他前面的数大于Codeforces Round #629 (Div. 3) A~D,F - 图36#card=math&code=%28k-1%29&id=iDA9O)个,同理,在他后面的数大于 Codeforces Round #629 (Div. 3) A~D,F - 图37#card=math&code=%28k-1%29&id=dsnFH) 个时才可以动后面,然后在任何情况下都可以前后都动( 在$(i=1) $时就相当于是动后面结果不冲突)

以只动前面为例

Codeforces Round #629 (Div. 3) A~D,F - 图38%20-a%5Bj%5D)%20%2B%20k#card=math&code=tem1%20%3D%20%28%5Csum%5Climits_%7Bj%3D1%7D%5Ei%28%28a%5Bi%5D%20-%201%29%20-a%5Bj%5D%29%20%2B%20k&id=syvoU)

化简一下发现

Codeforces Round #629 (Div. 3) A~D,F - 图39%20-%5Csum%5Climits%7Bj%3D1%7D%5Eia%5Bj%5D%20%2B%20k#card=math&code=tem1%20%3D%20%5Csum%5Climits%7Bj%3D1%7D%5Ei%28a%5Bi%5D%20-%201%29%20-%5Csum%5Climits_%7Bj%3D1%7D%5Eia%5Bj%5D%20%2B%20k&id=WVVcS)

就是 Codeforces Round #629 (Div. 3) A~D,F - 图40-a%5Bi%5D#card=math&code=i%2A%28a%5Bi%5D-1%29-a%5Bi%5D&id=fh1yE) 的前缀和 Codeforces Round #629 (Div. 3) A~D,F - 图41 ,提前搞一个前缀和可以降低时间复杂度

只动后面同理

Codeforces Round #629 (Div. 3) A~D,F - 图42%20%2B%20k#card=math&code=tmp2%20%3D%20%5Csum%5Climits%7Bj%3Di%7D%5Ena%5Bi%5D%20-%5Csum%5Climits%7Bj%3Di%7D%5En%28a%5Bj%5D%20%2B%201%29%20%2B%20k&id=iSFA1)

动两边,这时相等的数的个数恰好为 Codeforces Round #629 (Div. 3) A~D,F - 图43 ,把他们都搞成 Codeforces Round #629 (Div. 3) A~D,F - 图44 然后再减掉多余的

Codeforces Round #629 (Div. 3) A~D,F - 图45#card=math&code=tmp3%20%3D%20%5Csum%5Climits%7Bj%3Di%7D%5Ena%5Bj%5D%20-%20%5Csum%5Climits%7Bj%3D1%7D%5Eia%5Bj%5D%20%2B%20%5Csum%5Climits%7Bj%3D1%7D%5Eia%5Bi%5D%20-%20%5Csum%5Climits%7Bj%3Di%7D%5Ena%5Bi%5D%20-%20%28n%20-%20k%29&id=qswOc)

记录好前缀和 和(后缀和?)就可以用 Codeforces Round #629 (Div. 3) A~D,F - 图46#card=math&code=%5Cmathcal%7BO%7D%28n%29&id=wi7Mh) 的复杂度解决掉这个问题了

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. const ll inf = 1e17;
  5. ll a[200009];
  6. ll cnt[200009];
  7. ll sumq[200009], sumh[200009];
  8. int main() {
  9. int n, k;
  10. ll ans = inf;
  11. scanf("%d%d", &n, &k);
  12. for (int i = 1; i <= n; i++) {
  13. scanf("%lld", &a[i]);
  14. }
  15. sort(a + 1, a + 1 + n);
  16. for (int i = 1; i <= n; i++) sumq[i] = sumq[i - 1] + a[i];
  17. for (int i = n; i >= 1; i--) sumh[i] = sumh[i + 1] + a[i];
  18. for (int i = 1; i <= n; i++) {
  19. if (a[i] == a[i - 1])cnt[i] = cnt[i - 1] + 1;
  20. else cnt[i] = 1;
  21. if (cnt[i] >= k) {
  22. puts("0");
  23. return 0;
  24. }
  25. }
  26. for (int i = 1; i <= n; i++) {
  27. if (i >= k) {
  28. ll tem1 = i * (a[i] - 1) - sumq[i] + k;
  29. ans = min(tem1, ans);
  30. }
  31. if (n - i + 1 >= k) {
  32. ll tem2 = n - i + 1;
  33. tem2 = sumh[i] - tem2 * (a[i] + 1) + k;
  34. ans = min(tem2, ans);
  35. }
  36. if (i < k && (n - i + 1) < k) {
  37. ll tem3 = i * a[i] - sumq[i] + sumh[i] - (n - i + 1) * a[i] - (n - k);
  38. ans = min(tem3, ans);
  39. }
  40. }
  41. printf("%lld\n", ans);
  42. return 0;
  43. }

便捷写法

  1. int main() {
  2. cin.tie(nullptr)->sync_with_stdio(false);
  3. int n, k;
  4. cin >> n >> k;
  5. vector<ll> a(n);
  6. for (ll &x : a) cin >> x;
  7. sort(a.begin(), a.end());
  8. for (int i = 0; i + k - 1 < n; ++i) {
  9. if (a[i] == a[i + k - 1])
  10. return printf("0\n"), 0;
  11. }
  12. ll lcost = 0;
  13. ll rcost = 0;
  14. for (int i = 0; i < k; ++i) {
  15. lcost += a[k - 1] - a[i];
  16. rcost += a[n - 1 - i] - a[n - k];
  17. }
  18. for (int j = k; j < n; ++j) {
  19. if (a[k - 1] == a[j]) lcost--;
  20. if (a[n - k] == a[n - 1 - j]) rcost--;
  21. }
  22. ll sum = 0;
  23. for (int i = 0; i < n - 1 - i; ++i) sum += a[n - 1 - i] - a[i];
  24. ll ans = min(sum - (n - k), min(lcost, rcost));
  25. cout << ans;
  26. }

D: CodeForces 1324D - Pair of Topics

Codeforces Round #629 (Div. 3) A~D,F - 图47

Input

  1. 5
  2. 4 8 2 6 2
  3. 4 5 4 1 3

Output

  1. 7

Input

  1. 4
  2. 1 3 2 4
  3. 1 3 2 4

Output

  1. 0

题意:

Codeforces Round #629 (Div. 3) A~D,F - 图48 个主题,第 Codeforces Round #629 (Div. 3) A~D,F - 图49 个主题有 Codeforces Round #629 (Div. 3) A~D,F - 图50 个老师, Codeforces Round #629 (Div. 3) A~D,F - 图51 个学生。

需要选择两个主题,这两个主题的老师数大于学生数

也就是说选择两个下标保证 Codeforces Round #629 (Div. 3) A~D,F - 图52

输出可行的选择种类数

思路:

思维转为一下,让我们比较 Codeforces Round #629 (Div. 3) A~D,F - 图53 的,直接求 Codeforces Round #629 (Div. 3) A~D,F - 图54有几个。

当然直接对数组操作以后是无序的,两重for会超时,所以需要我们先进行一次sort,然后判断累加。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int N = 2e5 + 50;
  5. ll a[N], b[N];
  6. int main() {
  7. //freopen("in.txt", "r", stdin);
  8. int n; cin >> n;
  9. ll cnt = 0;
  10. for (int i = 0; i < n; ++i)cin >> a[i];
  11. for (int i = 0; i < n; ++i)cin >> b[i];
  12. for (int i = 0; i < n; ++i)a[i] -= b[i];
  13. sort(a, a + n);
  14. int l = n - 1;
  15. for (int i = 0; i < n; i++){
  16. while (l >= 0 && a[i] + a[l] > 0)l--;
  17. cnt+= n - max(i, l) - 1;
  18. }
  19. cout << cnt << endl;
  20. }