IAEPC Preliminary Contest (Codeforces Round 999, Div. 1 + Div. 2)
A - Kevin and Arithmetic
题意
给定\(n\)个整数\(a_1,a_2,···,a_n\),和初始化为\(0\)的整数\(s\)。将\(a_i\)加到\(s\)上,若得到的\(s\)是偶数,加\(1\)分,然后\(s%=2\)。重新排列\(a\),使得分最大化
思路
详情见代码
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int mxn = 1e6 + 5;
void solve()
{
int n, cnt = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
int a;
cin >> a;
if (a & 1)
{
cnt++;
}
}
if (!cnt)
{
cout << 1 << endl;
return;
}
if (cnt == n)
{
cout << n - 1 << endl;
return;
}
cout << cnt + 1 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
B - Kevin and Arithmetic
题意
给定\(n\)根一直长度的棍子,问是否能挑\(4\)根组成等腰梯形(长方形和正方形也是等腰梯形)。
思路
找最大腰,然后找一条最小边,这样最优。用\(A,B,C\)表示上底边,腰和下底边,则要满足\(A+2B>C\)
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int mxn = 1e6 + 5;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a.begin(), a.end());
int A, B, p;
for (int j = n - 1; j > 0; j--)
{
if (a[j] == a[j - 1])
{
B = a[j];
p = j;
for (int i = 0; i < n; i++)
{
if (i == p || i == p - 1)
{
continue;
}
A = a[i];
auto q = lower_bound(a.begin(), a.end(), A);
while (q - a.begin() == i || q - a.begin() == p || q - a.begin() == p - 1)
{
q++;
}
if (q == a.end() || a[q - a.begin()] >= A + 2 * B)
{
continue;
}
cout << A << " " << B << " " << B << " " << a[q - a.begin()] << endl;
return;
}
}
}
cout << -1 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
C - Kevin and Puzzle
题意
\(n\)个人站成一排,\(a_i\)表示第\(i\)个人说左边(包括自己),有多少人是骗子(骗子可以说真话也可以说谎)。两个骗子不能相邻。问有多少组合。
思路
详情见代码
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int mxn = 2e5 + 5;
const int mod = 998244353;
int dp[mxn][2]; // dp[i][0]表示到第i个人并且他不诚实的方案数
int cnt[mxn]; // cnt[i]表示如果第i个人说谎,[1,i)说谎的人数
void clear(int n)
{
for (int i = 1; i <= n; i++)
{
dp[i][0] = dp[i][1] = 0;
}
}
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
if (a[1])
{
cnt[1] = dp[1][0] = 1;
}
else
{
dp[1][1] = dp[1][0] = cnt[1] = 1;
}
for (int i = 2; i <= n; i++)
{
// 当前不诚实
dp[i][0] = dp[i - 1][1]; // 如果不诚实了,上一个人一定诚实
cnt[i] = a[i - 1] + 1;
// 当前诚实
if (a[i] < i)
{
if (a[i] == a[i - 1]) // 上一个人诚实
{
dp[i][1] = dp[i - 1][1];
}
if (a[i] == cnt[i - 1]) // 上一个人说谎
{
dp[i][1] += dp[i - 1][0];
dp[i][1] %= mod;
}
}
}
cout << (dp[n][0] + dp[n][1]) % mod << endl;
clear(n);
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
D - Kevin and Numbers
题意
给定长度为\(n\)的正整数序列\(a\),可以执行以下操作任意次:选择两个数\(x,y(|x-y|\le 1)\)删除,添加一个数\(x+y\)。问能否得到长度为\(m\)的序列\(b\)
思路
注意\(|x-y|\le 1\)这个条件,这让我们可以拆解\(b\)——如果\(b_i\)是偶数,那只能拆成两个\(\frac {b_i} 2\);如果\(b_i\)是奇数,那只能拆成\(\frac {b_i} 2\)和\(\frac {{b_i}+1} 2\)
代码
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int mxn = 2e5 + 5;
void solve()
{
int n, m, A = 0, B = 0;
cin >> n >> m;
priority_queue<int> a, b;
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
A += x;
a.push(x);
}
for (int i = 0; i < m; i++)
{
int x;
cin >> x;
B += x;
b.push(x);
}
if (A != B)
{
cout << "NO" << endl;
return;
}
while (a.size() && b.size())
{
int t = b.top();
b.pop();
if (t == a.top())
{
a.pop();
}
else if (t < a.top())
{
cout << "NO" << endl;
return;
}
else
{
b.push(t >> 1);
b.push(t + 1 >> 1);
}
}
if (b.size())
{
cout << "NO" << endl;
return;
}
cout << "YES" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号