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\),然后用组合数算:

\[\sum_{c_0=0}^{\lfloor\frac{k}{2}\rfloor} \binom{C_0}{c_0}\binom{C_1}{k-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 出的模拟赛中学来的。

posted @ 2024-08-07 09:39  lingfunny  阅读(62)  评论(0编辑  收藏  举报