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

给定 sts 中有 ?,判断是否能把 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,让 03

可以枚举需要除以 k3 的区间,显然是 log 级别的,并且是 [3k1,3k)

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 的数量 c0k2,枚举这个 c0,然后用组合数算:

c0=0k2(C0c0)(C1kc0)

这里的 C0 是序列中的 0 的数量,C1 同理。

for (int c0 = 0; c0 <= x; ++c0) {
		ans += C(c[0], c0) * C(c[1], k - c0);
	}

G

显然是一个三分题,注意到 37=2187>999,可以通过此题。

具体的,你询问 m1,m2 后,可以确定 xm1m1<xm2m2<x,每次令区间缩减为原来的 23 最优。

实际上,应该有一个更优的做法叫做斐波那契三分法,不过这里应该没必要使用。可能不叫这个名字。。

原来是斐波那契查找,我记错了。这个的应用是在极限数据下减少保证二分次数最少。negiizhao 出的模拟赛中学来的。

posted @   lingfunny  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示