Codeforces Round #796 (Div. 2)
作者:互联网
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\),给定以下两种操作:
- 从\(a\)中选择两个数\(a_i\)和\(a_j\),将这两个数从\(a\)中删除,然后再向\(a\)中插入\(a_i + a_j\)。
- 从\(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