A. Odd Selection
题意:
给定 n 个数,是否能选 k 个数和为奇数
分析:
和为奇数只有一种情况:n 个偶数 + k 个奇数( n 任意,k 为奇数)枚举奇数个数即可
void solve()
{
a = b = 0;
cin >> n >> k;
for (int i = 1, x; i <= n; i++)
{
cin >> x;
if (x & 1)
a++;
else
b++;
}
bool f = false;
for (int i = 1; i <= a; i += 2)
{
if (k - i <= b && k - i >= 0)
{
f = true;
break;
}
}
if (f)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
B. Subsequence Hate
题意:
给定 01 串,操作为 0 与 1 相互转化,要求最少的操作次数使任意子序列中不含010
和101
分析:
不含101
以及010
,所以只有所有的的0
在一边,所有的1
在一边这种情况,分别记录前缀0
和1
的个数枚举更新答案,最后再与改为全0
和全1
的操作次数取 min
void solve()
{
mst(s1, 0), mst(s0, 0);
idx0 = idx1 = 0;
res = INF;
cin >> s;
s = " " + s;
int len = s.size() - 1;
for (int i = 1; i <= len; i++)
{
s1[i] = s1[i - 1], s0[i] = s0[i - 1];
if (s[i] == '1')
{
idx1++;
s1[i] = s1[i - 1] + 1;
}
else if (s[i] == '0')
{
idx0++;
s0[i] = s0[i - 1] + 1;
}
}
for (int i = 1; i <= len; i++)
{
int t1 = s1[i] - s1[0] + s0[len] - s0[i];
int t2 = s0[i] - s0[0] + s1[len] - s1[i];
res = min(res, min(t1, t2));
}
res = min(res, min(idx1, idx0));
cout << res << endl;
}
C. Game On Leaves
题意:
给定 n 个节点的无根树。两名选手轮流操作,每次可以选择一个叶节点并删除它以及所有和它相连的边,删除节点 x 的选手胜利,判断先手是否有必胜策略。
分析:
必胜态:到最后 x 上有偶数条边
- 特判:如果 x 刚开始就在叶子节点上,那么先手必然胜利
- 这时我们可以知道,与 x 节点相连的边数一定 \(\geq 2\)。所以由于两个人都实行最优策略,所以到了仅剩下两条边与 x 相连时就只会开始删其他叶节点来保证必胜态
void solve()
{
idx = 0;
cin >> n >> k;
for (int i = 1, a, b; i < n; i++)
{
cin >> a >> b;
if (a == k || b == k)
idx++;
}
if (idx < 2 || n % 2 == 0)
cout << "Ayush" << endl;
else
cout << "Ashish" << endl;
}