IAEPC Preliminary Contest (Codeforces Round 999, Div. 1 + Div. 2)
A. Kevin and Arithmetic
题目大意
给你一个数组,每次可以选择一个其中一个数字加给s(初始值是0),如果s是偶数可以加一分,之后不加分,一直将s/2直到s是奇数再继续操作,问最大的分数是多少
解题思路
由于不断执行s/2之后一定是一个奇数,所以只要加上奇数就能对答案贡献1,因此统计奇数的数量即可,需要额外处理第一次是偶数的情况
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n, even = 0, odd = 0;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
if (a[i] % 2) {
even += 1;
} else {
odd += 1;
}
}
std::cout << (odd > 0) * 2 + even - 1 << "\n";
}
}
B. Kevin and Geometry
题目大意
给你一个数组,选出四个数字组成等腰梯形并给出任意一个方案,不可能则输出-1
解题思路
想要构成等腰梯形只要满足上底加两腰大于下底即可(假设上底小于等于下底),因此可以贪心的选择最大的两腰,然后在剩余的数字中遍历出相邻的两个一直判断即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n, max2 = 0, f = 1;
std::cin >> n;
std::vector<int> a(n);
std::map<int, int> mp;
for (int i = 0; i < n; i++) {
std::cin >> a[i];
if (mp[a[i]]) {
max2 = std::max(max2, a[i]);
}
mp[a[i]]++;
}
std::sort(a.begin(), a.end());
if (mp.size() == n) {
std::cout << -1 << "\n";
} else {
a.erase(std::find(a.begin(), a.end(), max2));
a.erase(std::find(a.begin(), a.end(), max2));
for (int i = 1; i < n - 2 && f; i++) {
if (a[i - 1] + max2 * 2 > a[i]) {
std::cout << a[i - 1] << " " << max2 << " " << max2 << " " << a[i] << "\n";
f = 0;
}
}
if (f) {
std::cout << -1 << "\n";
}
}
}
}
C. Kevin and Puzzle
题目大意
给你一个数组a,第i个数字表示第i个人左侧有
解题思路
每个人要么是诚实的,要么是说谎者,假设第i个人是诚实,第i-1个人也是诚实的,则将i-1诚实方案数累加到i诚实方案数,如果第i-1个人是说谎者,将i-1的说谎方案数加到i诚实方案数(不能有连续说谎者);假设第i个人是说谎者,i-1只能是诚实的(不能有连续说谎者),将i-1的诚实方案数加到i说谎方案数即可。dp下去就能得到最后的答案
代码实现
#include <bits/stdc++.h>
using i64 = long long;
const int MOD = 998244353;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n;
std::cin >> n;
std::vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
std::vector<std::vector<int>> dp(n + 1, std::vector<int>(2));
dp[1][0] = 1;
dp[1][1] = a[1] == 0;
for (int i = 2; i <= n; i++) {
// i诚实
if (a[i] == a[i - 1]) {
dp[i][1] = (dp[i][1] + dp[i - 1][1]) % MOD;
}
if (a[i] == a[i - 2] + 1) {
dp[i][1] = (dp[i][1] + dp[i - 1][0]) % MOD;
}
// i说谎
dp[i][0] = (dp[i][0] + dp[i - 1][1]) % MOD;
}
std::cout << (dp[n][0] + dp[n][1]) % MOD << "\n";
}
}
D. Kevin and Numbers
题目大意
给你两个数组ab,你可以在a中选两个绝对值不大于1的数合并,进行操作,问a能不能变成b
解题思路
正难则反,a能不断合并变成b,b也能不断分解变成a,只需要统计ab元素,将b中的元素不断分解与a匹配即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n, m;
std::cin >> n >> m;
std::map<int, int> mp1, mp2;
std::vector<int> a(n), b(m);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
mp1[a[i]]++;
}
for (int i = 0; i < m; i++) {
std::cin >> b[i];
mp2[b[i]]++;
}
if (std::accumulate(a.begin(), a.end(), 0ll) != accumulate(b.begin(), b.end(), 0ll)) {
std::cout << "No\n";
continue;
}
while (!mp2.empty() && n) {
auto [x, y] = *mp2.rbegin();
mp2.erase(x);
if (mp1.count(x)) {
int match = std::min(mp1[x], y);
mp1[x] -= match;
y -= match;
n -= match;
if (mp1[x] == 0) {
mp1.erase(x);
}
}
if (y) {
if (x == 1) {
break;
}
mp2[x / 2] += y;
mp2[x - x / 2] += y;
}
}
if (!n) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
}
E. Kevin and And
题目大意
给你两个数组ab,你可以执行k次操作,每次操作在ab中分别选两个数字让
解题思路
显然操作的次数越多最后求和会是单调不递增的,所以可以让操作次数拉满。观察数据范围发现m的范围非常小,因此可以考虑状压,枚举b数组选择的所有状态,预处理出选择的子集,再枚举选择的子集带给
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t;
std::cin >> t;
while (t--) {
int n, m, k;
std::cin >> n >> m >> k;
std::vector<int> a(n), b(m);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
for (int i = 0; i < m; i++) {
std::cin >> b[i];
}
std::vector<int> sum(1 << m, (1 << 30) - 1);
for (int bit = 0; bit < (1 << m); bit++) {
for (int j = 0; j < m; j++) {
if (bit >> j & 1) {
sum[bit] &= b[j];
}
}
}
std::priority_queue<int> pq;
for (int i = 0; i < n; i++) {
std::vector<int> dp(m + 1);
for (int bit = 0; bit < (1 << m); bit++) {
int cnt = __builtin_popcount(bit);
dp[cnt] = std::max(dp[cnt], a[i] ^ (a[i] & sum[bit]));
}
for (int j = 0; j < m; j++) {
pq.push(dp[j + 1] - dp[j]);
}
}
i64 ans = accumulate(a.begin(), a.end(), 0ll);
while (!pq.empty() && k--) {
ans -= pq.top();
pq.pop();
}
std::cout << ans << "\n";
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具