C/C++教程

AtCoder Beginner Contest 238题解

本文主要是介绍AtCoder Beginner Contest 238题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

本场打得比较摆烂,只到E题QAQ

A - Exponential or Quadratic

题目描述:给定正整数\(n\),判断式子\(2^n > n^2\)是否成立。

思路:显然只有当n = 2 , 3 , 4时不成立

时间复杂度:\(O(1)\)

参考代码:

void solve() {
	int n;
	cin >> n;
	if (n != 2 && n != 3 && n != 4) cout << "Yes\n";
	else cout << "No\n";
	return;
}

B - Pizza

题目描述:给定一块披萨,然后给你一个数组\(A\),每次你需要转动\(a_i\)角度之后,在12点钟方向切一刀。问最终所有扇形中角度的最大值。

思路:显然让披萨转动和让刀转动等价,我们让刀转动,然后切的时候将对应角度标记为\(1\)。最后再使用双指针求最大值即可。

时间复杂度:\(O(n)\)

参考代码:

void solve() {
	int n;
	cin >> n;
	vector<int>a(n + 1, 0);
	for (int i = 1; i <= n; ++i) cin >> a[i];
	vector<int>deg(361, 0);
	deg[0] = 1; deg[360] = 1;
	int cur = 0;
	for (int i = 1; i <= n; ++i) {
		cur = (cur + a[i]) % 360;
		deg[cur] = 1;
	}
	int res = 0;
	int p = 0, q = 1;
	while (p < 360) {
		while (deg[q] == 0) ++q;
		res = max(res, q - p);
		p = q;
		q = p + 1;
	}
	cout << res << '\n';
	return;
}

C - digitnum

题目描述:定义\(f(x)\)表示与\(x\)位数相同且小于等于\(x\)的数字的个数,对于给定的\(n\),求\(\sum\limits_{i = 1}^{n}f(i)\)。

思路:根据题意显然将\(n\)按照\(10\)的幂次分段,对于每一段,如果有\(m\)个数字,那么对答案的贡献就是\(\frac{m * (m + 1)}{2}\) 。比如\(10 \sim 99\)就是从\(1 \sim 90\)的累加。

时间复杂度:\(O(log_{10}n)\)

参考代码:

void solve() {
	long long n;
	cin >> n;
	long long res = 0;
	long long p = 10, q = 1;
	const int mod = 998244353;
	while (true) {
		long long m = min(n , p - 1) - q + 1;
		m %= mod;
		res = (res + (m * (m + 1) / 2) % mod) % mod;
		if (p > n) break;
		p *= 10;
		q *= 10;
	}
	cout << res << '\n';
	return;
}

D - AND and SUM

题目描述:对于给定的\(a , s\),是否存在\(x , y\)使得以下条件成立:

  • x AND y = a
  • x + y = s

多组数据,对于每组数据若存在输出Yes,否则输出No

思路:比较明显,我们可以先通过第一个约束条件将\(x , y\)的二进制表示中必须为\(1\)的找出来,求和为\(sum\)。若\(sum> s\)则显然没有;否则\(s = s - sum\)。然后对于每一个\(x , y\)没使用的二进制位,贪心的从\(s\)中减去,若最终\(s = 0\)则存在,否则不存在。

时间复杂度:\(O(60T)\)

参考代码:

void solve() {
	long long a, s;
	cin >> a >> s;
	vector<int>cnt(60, 0);
	long long sum = 0;
	for (int i = 0; i < 60; ++i) {
		cnt[i] += (a >> i) & 1;
		if (cnt[i]) sum += 2ll << i;
	}
	if (sum > s) {
		cout << "No" << '\n';
		return;
	}
	s -= sum;
	for (int i = 59; i >= 0; --i) {
		if (cnt[i]) continue;
		long long dx = 1ll << i;
		if (dx <= s) s -= dx;
	}
	if (s == 0) cout << "Yes" << '\n';
	else cout << "No" << '\n';
	return;
}

E - Range Sums

题目描述:给你一个整数\(n\),表示有一个长度为\(n\)的正整数数组,告诉你\(q\)个条件,每个条件的形式为 lr rs,表示\(\sum\limits_{i = lr}^{rs} a_i\) 。问是否可以通过这些条件知道\(\sum\limits_{i = 1}^{n}a_i\)。若能输出Yes,否则输出No

思路:比较明显的图论题。对于每一个条件,可以根据前缀和的知识,抽象成从\(lr - 1\)到\(rs\)存在一条无向边。我们将条件读入并转化成图后,从\(0\)开始dfs。若最终能访问到第\(n\)个点,则表示可以求出题目的和式,否则不能。

时间复杂度:\(O(n)\)

参考代码:

void solve() {
	int n, q;
	cin >> n >> q;
	vector<vector<int>>graph(n + 1);
	int u, v;
	for (int i = 1; i <= q; ++i) {
		cin >> u >> v;
		graph[u - 1].push_back(v);
		graph[v].push_back(u - 1);
	}
	vector<bool>vis(n + 1, false);
	auto dfs = [&](auto dfs, int u)->void {
		if (vis[u]) return;
		vis[u] = true;
		for (auto v : graph[u]) dfs(dfs, v);
		return;
	};
	dfs(dfs, 0);
	if (vis[n]) cout << "Yes" << '\n';
	else cout << "No" << '\n';
	return;
}
这篇关于AtCoder Beginner Contest 238题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!