源代码:ACM/OpenjudgeNow/Codeforces at master · abmcar/ACM (github.com)
更好的阅读体验: Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final Round) (A-C题解) - Abmcar’s 茶水间
A. Maximum Cake Tastiness
题目大意:
思路:
可以证明通过旋转可以使得最大的蛋糕和次大的蛋糕相邻
因此最大美味为最大+次大
代码:
void solution()
{
int maxn1, maxn2;
maxn1 = maxn2 = 0;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; i++)
cin >> nums[i];
sort(nums.begin(), nums.end(), greater<int>());
cout << nums[0] + nums[1] << endl;
}
B. Prefix Removals
题目大意:
思路:
B题的题目非常具有迷惑性,一直让找最长的前缀
但我们可以发现,对于任意最长前缀 p r e f i x 0 = p r e f i x 1 + p r e f i x 2 prefix_0=prefix1+prefix2 prefix0=prefix1+prefix2
如果先处理掉 p r e f i x 1 prefix1 prefix1再处理 p r e f i x 2 prefix2 prefix2和直接处理 p r e f i x 0 prefix0 prefix0没有区别
由此逐步处理,单个字母单个字母地处理对最后结果同样没有影响
所以如果我们找到一个字母,在它之后的字符串中该字母没有出现过,则停止
我们可以记录下当前位置前每个字母的个数,若当前位置该字母个数等于整个字符串中该字母个数,则停止
剩下部分即为最终字符串
代码:
void solution()
{
map<char, int> M, M1;
string ori;
cin >> ori;
for (char it : ori)
M[it]++;
int cnt = 0;
for (int i = 0; i < ori.size(); i++)
{
M1[ori[i]]++;
if (M1[ori[i]] == M[ori[i]])
{
cnt = i;
break;
}
}
for (int i = cnt; i < ori.size(); i++)
cout << ori[i];
cout << endl;
}
C. Alice and the Cake
题目大意:
思路:
发现 ⌊ w 2 ⌋ + ⌈ w 2 ⌉ = w \lfloor\frac{w}2\rfloor+\lceil\frac w 2\rceil = w ⌊2w⌋+⌈2w⌉=w
同时也发现,如果按照贪心的思路每次取某几个相加会有后效性,因此无法贪心
正难则反,我们可以从w出发取dfs判断是否可以分成某个数
同时,如果dfs到最后还没有在数组里出现,则直接可以判为NO,因为此时其余数之和已经不可能等于w了
代码:
int t, n;
map<int, int> M;
bool ok;
void solution()
{
cin.tie(nullptr)->sync_with_stdio(false);
cin >> n;
queue<int> Q;
M.clear();
int tot = 0;
int cnt = 0;
ok = true;
for (int i = 1; i <= n; i++)
{
int tmp;
cin >> tmp;
tot += tmp;
M[tmp]++;
}
function<void(int)> dfs = [&](int nowNum) -> void {
if (!ok)
return;
if (M[nowNum])
{
M[nowNum]--;
return;
}
if (nowNum >= 2)
{
dfs(nowNum / 2);
dfs((nowNum + 1) / 2);
}
else
ok = false;
};
dfs(tot);
for (auto it : M)
if (it.second)
ok = false;
if (ok)
cout << "YES" << endl;
else
cout << "NO" << endl;
}