比赛地址:Codeforces Round #571 (Div. 2)
A. Vus the Cossack and a Contest
题目大意:有 \(n\) 个人,你有 \(m\) 支笔和 \(k\) 本笔记本,问可不可以给每人一支笔一本笔记本。
解题思路:签到题,直接判断大小即可。
#include <cstdio>
int n, m, k;
int main() {
scanf("%d%d%d", &n, &m, &k);
if ((m >= n) && (k >= n)) printf("Yes");
else printf("No");
return 0;
}
C. Vus the Cossack and Strings
题目大意:给你两个 01 串 \(a\) 和 \(b\) ,保证长度 \(len_a > len_b\) 现在在 \(a\) 中找出所有长度为 \(len_b\) 的子串 \(c\) ,定义函数 \(f(x,y) = x,y \mbox{字符不同的位置数}\) ,求所有的 \(f(b,c)\) 的值有多少个为偶数。
解题思路:不妨设 \(b\) 串有 \(m\) 个 1 , \(c\) 串有 \(n\) 个 1 ,且 \(b\) 、 \(c\) 中同为 1 的位置数为 \(k\) 。那么 \(b\) 、 \(c\) 中字符不同的位置数有 \(cnt = m - k + n - k = m + n - 2k\) ,因此当 \(m + n\) 为偶数时, \(cnt\) 为偶数,根据数论知识 \(m + n\) 为偶数的充要条件是 \(m \equiv n\ (mod\;2)\) ,因此我们只需要统计每一个子串中 1 的个数就好了,这是可以在 \(\Theta (n)\) 的时间内完成的。
奇技淫巧:众所周知,取模运算是很慢的,怎么加速这一过程呢,我们可以通过 \(n & 1\) 来代替,如果 \(n & 1 = 1\) ,那么 \(n\;mod\;2 = 1\) ,否则 \(2\;|\;n\) ,我们怎么判断相等呢?这个时候可以用异或运算浪一波,两个数相等时,其异或运算结果为 0 ,否则为 1 。
#include <cstdio>
#include <cstring>
const int MAXN = 1e6 + 5;
int lena, lenb, cnt, tmp, ans;
char a[MAXN], b[MAXN];
int main() {
scanf("%s%s", a + 1, b + 1);
lena = strlen(a + 1);
lenb = strlen(b + 1);
for (int i = 1; i <= lenb; ++i) {
if (b[i] == '1')
++cnt;
if (a[i] == '1')
++tmp;
}
if ((cnt & 1) ^ (tmp & 1) == 0)
++ans;
for (int i = lenb + 1; i <= lena; ++i) {
if (a[i - lenb] == '1')
--tmp;
if (a[i] == '1')
++tmp;
if ((cnt & 1) ^ (tmp & 1) == 0)
++ans;
}
printf("%d", ans);
return 0;
}
D. Vus the Cossack and Numbers
题目大意:给你一个长度为 \(n\) 的实数序列 \(a\) ,你可以将其中的每一个元素变成 \(b\) ,其中 \(b = \lfloor a \rfloor\) 或 \(\lceil a \rceil\) ,给出一种方案,使得 \(\sum\limits_{i = 1}^{n} b_i = 0\) ,题目保证有解。
解题思路:我们可以先让每一个 \(b\) 最小化,这样一定会使得 \(\sum\limits_{i = 1}^{n} b_i < 0\) ,然后再一个个调大 \(b\) ,使其变成 \(b + 1\) ,逐渐将总和调成 0 。
值得注意的是:因为 \(a_i\) 是实数,所以有可能出现 \(a_i\) 是整数的情况,在这种情况下,对应的 \(b_i\) 只有一种取值,也就不能调大了。
#include <cstdio>
#include <cmath>
const int MAXN = 1e5 + 5;
int n, cnt;
int b[MAXN];
double a[MAXN];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%lf", &a[i]);
b[i] = floor(a[i]);
cnt += b[i];
}
cnt *= -1;
for (int i = 1; i <= cnt; ++i) {
if (a[i] != b[i]) b[i] += 1;
else ++cnt;
}
for (int i = 1; i <= n; ++i) {
printf("%d\n", b[i]);
}
return 0;
}