A.Odd Selection
给你
n
n
n个数,问能不能在其中选
x
x
x个数使得
s
u
m
sum
sum为奇数。
我们知道,只有选 奇数个数的 奇数,
s
u
m
sum
sum才会是奇数。
数据范围不大,我们直接枚举每一种取 奇数个数的 奇数 的情况,然后再看看偶数够不够取,即可
int n, m, k, x;
void solve()
{
cin >> n >> x;
int odd = 0, ev = 0;
for (int i = 1; i <= n; i++)
{
cin >> k;
if (k % 2 == 1)odd++;
else ev++;
}
bool f = 0;
for (int i = 0; i <= odd; i++)
if (i % 2 == 1 && i <= x && x - i <= ev)f = 1;
if (f)cout << "YES\n";
else cout << "NO\n";
}
B.Subsequence Hate
给一个01串,每次操作可以把任意一位取反,问最少操作数使得这个01串不存在子序列"010" 或 “101”。显而易见,要把串变成全是0或全是1,或一边全是0另一边全是1。简单实现题,详解见代码。
int pre[1005], suf[1005];//1的个数的前缀和后缀
void solve()
{
memset(pre, 0, sizeof(pre));
memset(suf, 0, sizeof(suf));
string s; cin >> s;
int len = s.size();
s = ' ' + s;//方便后续操作
pre[0] = 0;
suf[len + 1] = 0;
for (int i = 1; i <= len; i++)
pre[i] = pre[i - 1] + (s[i] - '0');
for (int i = len; i >= 1; i--)
suf[i] = suf[i + 1] + (s[i] - '0');
//ans0表示在下标为i时,[1, i-1]改1为0的次数(即1的个数) + [i, len]改0为1的次数(即0的个数)
//ans1表示在下标为i时,[1, i-1]改0为1的次数(即0的个数) + [i, len]改1为0的次数(即1的个数)
int ans1 = 100000, ans0 = 100000;
for (int i = 1; i <= len; i++)
{
ans1 = min(ans1, i - 1 - pre[i - 1] + suf[i]);
ans0 = min(ans0, pre[i - 1] + len - i + 1 - suf[i]);
}
cout << min(ans0, ans1) << endl;
}
C.Game On Leaves
给一颗有n-1条边和n个结点的树,编号为1~n,和一个特殊结点
x
x
x。
每次操作,取一个度为0或1结点删除, 谁删除了
x
x
x,谁就赢了。
Ayush先操作,Ashish后操作。每个人都采取最佳方案,问谁是winner。
可以很容易想到:谁都不想当 删去一个结点后
x
x
x的度就
≤
1
\leq1
≤1 人,除非没有其他可删结点了。因此他们一定会把所有其他无关紧要的可删结点优先删去,当
x
x
x的度
≤
1
\leq1
≤1,且没有其他无用的可删结点时,胜负便已分。
即当仅剩
x
x
x和另一个与
x
x
x相连的结点,游戏结束。
int n, m, k, x;
void solve()
{
int num = 0;//表示x的度
cin >> n >> x;
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
if (u == x || v == x)num++;
}
if (num <= 1)//x结点本身就是叶子结点,可以直接删去。num==0表示这棵树只有x这个结点
cout << "Ayush\n";
else
{ //n-2是除了 x和另一个与x相连的结点 外的结点数
//如果n-2是偶数,表示后操作的人就是前文所提的“谁都不想当的人”,接着下一步Ayush删除x结点,游戏结束
if ((n - 2) % 2 == 0)cout << "Ayush\n";
else cout << "Ashish\n";
}
}