ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #796 (Div. 2)

2022-06-04 02:03:19  阅读:187  来源: 互联网

标签:std 796 le int void Codeforces Div define


A. Cirno's Perfect Bitmasks Classroom

题意

给定一个数\(x\),输出满足\(x \operatorname{and} y > 0\)且\(x \operatorname{xor} y > 0\)的最小的\(y\)。

其中\(1 \le x \le 2^{30}\)。

思路

就是\(y\)和\(x\)的二进制表示至少要有一位不同,至少要有一位相同。

如果\(x\)的二进制里只有一个1,那么相同的那一位就确定了,还需要再把另外的一位变成1,贪心取最小的就可以了。

如果\(x\)的二进制表示有多个1,那么由于\(y\)要最小,所以\(y\)的二进制只会有一个1,贪心取最小的也就是\(y\)等于\(x\)的least significant bit。

AC代码
// Problem: A. Cirno's Perfect Bitmasks Classroom
// Contest: Codeforces - Codeforces Round #796 (Div. 2)
// URL: https://codeforces.com/contest/1688/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int x, y;
  std::cin >> x;
  y = (x & -x);
  if (x == y) {
    if (x == 1)
      y += 2;
    else
      y += 1;
  }
  std::cout << y << "\n";
}

B. Patchouli's Magical Talisman

题意

给定一个长度为\(n\)的数组\(a\),给定以下两种操作:

  1. 从\(a\)中选择两个数\(a_i\)和\(a_j\),将这两个数从\(a\)中删除,然后再向\(a\)中插入\(a_i + a_j\)。
  2. 从\(a\)中选择一个偶数\(x\),将其替换成\(\frac{x}{2}\)。

问让\(a\)中不包含偶数的最小操作次数。

其中\(1 \le n \le 2 \times {10}^5, 1 \le a_i \le {10}^9\)。

思路

\(a\)中没有偶数,答案为零。

注意到,消除\(a\)中的一个偶数至少要用一个操作,而如果\(a\)中已经有奇数了,那么就可以将这个奇数依次和所有偶数合并,那么每个偶数都可以通过一次操作删除,已经是最优的了。

如果\(a\)中没有奇数,那么就看怎么用最小的代价通过操作2造出奇数,这个枚举一下就可以了。

AC代码
// Problem: B. Patchouli's Magical Talisman
// Contest: Codeforces - Codeforces Round #796 (Div. 2)
// URL: https://codeforces.com/contest/1688/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n;
  std::cin >> n;

  int mi = INT_MAX;
  int c0 = 0, c1 = 0;
  for (int i = 0; i < n; ++i) {
    int x;
    std::cin >> x;

    if (x % 2 == 0)
      ++c0;
    else
      ++c1;

    int t = 0;
    while (x % 2 == 0) {
      ++t;
      x = x / 2;
    }
    if (t != 0)
      mi = std::min(mi, t);
  }

  if (c0 == 0)
    std::cout << "0\n";
  else if (c1 != 0)
    std::cout << c0 << "\n";
  else
    std::cout << mi + n - 1 << "\n";
}


C. Manipulating History

题意

有一个长度为\(1\)的初始字符串\(s_0\),通过一个长度为\(2n\)的操作序列\(t\),变成了\(s_n\)。

第\(i\)次操作就是将\(s_{i - 1}\)的一个子串\(t_{2i - 1}\)替换为\(t_{2i}\),从而得到\(s_i\),其中\(1 \le i \le n\)。

现在给出\(s_n\)和打乱了顺序的\(t\),要求还原出\(s_0\)。

所有字符串的长度之和不超过\(2 \times {10}^5\)。

思路

这题卡了好久导致E想出来了没来得及做。感觉智商是越来越不行了。

\(t\)和\(s_n\)中的所有字符,只有初始字符会出现奇数次,所以统计字符出现的次数,出现奇数次的那个就是答案。

证明的话,假设\(z\)表示没有打乱顺序的操作序列,除去\(z_1\),其他字符替换进\(s_i\)的时候会出现一次,被替换出\(s_i\)或者在\(s_n\)中会出现一次,所以一定是出现偶数次。

AC代码
// Problem: C. Manipulating History
// Contest: Codeforces - Codeforces Round #796 (Div. 2)
// URL: https://codeforces.com/contest/1688/problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n;
  std::cin >> n;

  std::vector<int> c(26, 0);
  for (int i = 0; i <= 2 * n; ++i) {
    std::string s;
    std::cin >> s;
    for (char ch : s) {
      ++c[ch - 'a'];
    }
  }
  logd(c);

  char ans = '?';
  for (int i = 0; i < 26; ++i) {
    if (c[i] & 1) {
      if (ans == '?') {
        ans = i + 'a';
      } else {
        assert(false);
      }
    }
  }
  std::cout << ans << "\n";
}

D. The Enchanted Forest

题意

在\(x\)轴上有\(n\)个点,给定一个长度为\(n\)的数组\(a_i\)表示每个点上初始的资源数。

每一秒每个点还会刷新\(1\)个资源。

你可以在这\(n\)个点中随意取一个点作为起点,每一秒你可以不移动或者移动到相邻点,并收集所在点的资源。

问\(k\)秒能收集到的最大资源数。

其中\(1 \le n \le 2 \times {10}^5, 1 \le k \le {10}^9, 1 \le a_i \le {10}^9\)。

思路

可以将资源数拆分乘两部分算,一部分是初始的,一部分是后面刷新出来的。

假设\(k < n\),那么第一部分借助前缀和可以线性算出最大值,第二部分是固定的直接高斯求和。

假设\(k \ge n\),那么第一部分就是固定的了,第二部分有两种策略,第一种是\(1 \rightarrow n \rightarrow 1 \dots\)左右横跳,第二种是等资源长好了在一次收过去割韭菜。猜结论加模拟了一下发现第二种策略不劣于第一种,然后就是数数了。

AC代码
// Problem: D. The Enchanted Forest
// Contest: Codeforces - Codeforces Round #796 (Div. 2)
// URL: https://codeforces.com/contest/1688/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n, k;
  std::cin >> n >> k;

  std::vector<i64> a(n + 1);
  for (int i = 1; i <= n; ++i)
    std::cin >> a[i];

  if (n == 1) {
    i64 ans = a[1] + k - 1;
    std::cout << ans << "\n";
    return;
  }

  std::vector<i64> b(n + 1);
  for (int i = 1; i <= n; ++i)
    b[i] = b[i - 1] + a[i];

  i64 ans = 0;
  if (k < n) {
    i64 ma = 0;
    for (int i = k; i <= n; ++i)
      ma = std::max(ma, b[i] - b[i - k]);
    ans += ma;
    ans += i64(1) * (k - 1) * k / 2;
  } else {
    ans += b[n];
    ans += i64(1) * (n - 1) * n / 2;
    k -= n;
    ans += i64(1) * k * n;
  }

  std::cout << ans << "\n";
}

E. Railway System

TBA。

F. Sanae and Giant Robot

TBA。

标签:std,796,le,int,void,Codeforces,Div,define
来源: https://www.cnblogs.com/zengzk/p/16341134.html

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有