ICode9

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

Codeforces Round #796 (Div. 2)

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

标签: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

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

ICode9版权所有