Codeforces Round 964 (Div. 4)
Codeforces Round 964 (Div. 4)
A
计算数位和。
void solve() {
int a = 0, n;
cin >> n;
while (n) a += n % 10, n /= 10;
cout << a << '\n';
}
B
模拟,直接枚举 4 种出牌顺序,按题目给的规则判断即可。
bool chk(int x1, int y1, int x2, int y2) {
int c1 = (x1 > y1) + (x2 > y2);
int c2 = (x1 < y1) + (x2 < y2);
return c1 > c2;
}
C
洗澡,数据给的很好,每个区间不重复,并且是按顺序的。只需要判断上一次结束到这一次开始之间的时间够不够 \(s\)。
void solve() {
int n, s, m;
cin >> n >> s >> m;
bool res = false;
int lst = 0;
for (int i = 0 ; i < n; ++i) {
int l, r;
cin >> l >> r;
if (l - lst >= s) res = true;
lst = r;
}
if (m - lst >= s) res = true;
cout << (res ? "YES" : "NO") << '\n';
}
D
给定 \(s\) 和 \(t\),\(s\) 中有 ?
,判断是否能把 \(t\) 改成 \(s\) 的子序列。
这个子序列显然贪心,按顺序匹配 \(t\),遇到 ?
就直接改成可以匹配 \(t\) 的字母。
for (int i = 0; i < n; ++i) {
if (j < m) {
if (s[i] == t[j]) ++j;
else if (s[i] == '?') s[i] = t[j++];
} else {
if (s[i] == '?') s[i] = 'a';
}
}
E
贪心地,首先把最小的改成 \(0\),剩下的操作全都选择让某个数除以 \(3\),让 \(0\) 乘 \(3\)。
可以枚举需要除以 \(k\) 次 \(3\) 的区间,显然是 $\log $ 级别的,并且是 \([3^{k-1}, 3^k)\)。
int lst = 1, cnt = 1;
for (int x = 3; x <= 600000; x *= 3, ++cnt) {
// [lst, x - 1]
int c = min(x - 1, r) - max(lst, l) + 1;
if (c > 0) ans += c * cnt;
lst = x;
}
F
数数题,可拓展。中位数是 \(1\) 的时候才有意义,否则不会对答案产生影响。
考虑什么时候中位数是 \(1\):当且仅当选出的 \(0\) 的数量 \(c_0 \le \lfloor\frac{k}{2}\rfloor\),枚举这个 \(c_0\),然后用组合数算:
这里的 \(C_0\) 是序列中的 \(0\) 的数量,\(C_1\) 同理。
for (int c0 = 0; c0 <= x; ++c0) {
ans += C(c[0], c0) * C(c[1], k - c0);
}
G
显然是一个三分题,注意到 \(3^7=2187 > 999\),可以通过此题。
具体的,你询问 \(m_1, m_2\) 后,可以确定 \(x\le m_1\) 或 \(m_1<x\le m_2\) 或 \(m_2<x\),每次令区间缩减为原来的 \(\frac{2}{3}\) 最优。
实际上,应该有一个更优的做法叫做斐波那契三分法,不过这里应该没必要使用。可能不叫这个名字。。
原来是斐波那契查找,我记错了。这个的应用是在极限数据下减少保证二分次数最少。negiizhao 出的模拟赛中学来的。
本文来自博客园,作者:lingfunny,转载请注明原文链接:https://www.cnblogs.com/lingfunny/p/18346408