返回顶部

AtCoder Beginner Contest 248 题解

AtCoder Beginner Contest 248 A$\sim $ E 题解

A - Lacked Number

题目描述:给你一个长度为\(9\)的数字字符串,求其中缺少的数字

思路:根据题意模拟即可

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

参考代码:

void solve() {
	string s;
	cin >> s;
	vector<int>cnt(10, 0);
	for (auto&& c : s) cnt[c - '0']++;
	for (int i = 0; i < 10; ++i) {
		if (cnt[i]) continue;
		cout << i << '\n';
		return;
	}
	return;
}

B - Slimes

题目描述:给你\(A , B , K\),求一个整数\(n\)使得\(A\times K^{n} \geq B\)

思路:根据题意模拟即可

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

参考代码:

void solve() {
	long long A, B, K;
	int res = 0;
	cin >> A >> B >> K;
	while (A < B) {
		++res;
		A *= K;
	}
	cout << res << '\n';
	return;
}

C - Dice Sum

题目描述:给你三个正整数\(N , M , K\),求长度为\(N\)的序列,且每个元素的值为正整数且不大于\(M\),且序列的和不大于\(K\)的序列数量。

思路:定义状态\(f_{i , j}\)表示前\(i\)个数和为\(j\)的方案数,则转移方程为:

\[f_{i , j} = \sum\limits_{k = j - m}^{j - 1}f_{i - 1 , k} \]

初始状态为:\(f_{0 , 0} = 1\);最终答案为:\(\sum\limits_{i = 1}^{k}f_{n , i}\)

参考代码:

const int mod = 998244353;
void solve() {
	int n, m, k;
	cin >> n >> m >> k;
	vector<vector<int>>f(n + 1, vector<int>(k + 1, 0));
	f[0][0] = 1;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= k; ++j) {
			for (int p = 1; p <= m; ++p) {
				if (p > j) break;
				f[i][j] = (f[i][j] + f[i - 1][j - p]) % mod;
			}
		}
	}
	int res = 0;
	for (int i = 1; i <= k; ++i) res = (res + f[n][i]) % mod;
	cout << res << '\n';
	return;
}

D - Range Count Query

题目描述:给你一个数字序列\(A\),然后有\(Q\)次询问,每次询问给定三个整数\(L , R , x\),表示求区间\([L , R]\)内值为\(x\)的元素的个数。

思路:比较基础的题目,考虑将不同数字的值当做下标,将下标存入vecctor中,每次询问直接在对应的vector中去二分即可,此处可以使用STL的库函数upper_boundlower_bound;注意后者在数组没空的时候会报错,所以需要特判一下。

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

参考代码:

const int N = 2e5 + 5;
vector<vector<int>>g(N);
void solve() {
	int n, a;
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> a;
		g[a].push_back(i);
	}
	int q, lr, rs, res;
	cin >> q;
	while (q--) {
		cin >> lr >> rs >> a;
		if (g[a].size() == 0) res = 0;
		else res = upper_bound(g[a].begin(), g[a].end(), rs) - lower_bound(g[a].begin(), g[a].end(), lr);
		cout << res << '\n';
	}
	return;
}

E - K-colinear Line

题目描述:给你\(N\)个点和一个整数\(K\),求经过至少\(K\)个点的直线的条数,若有无穷多,输出Infinity

思路:首先当\(K = 1\)时,答案显然为Infinity。当\(K \neq 1\)时,任意枚举两点求出所表示的直线,然后去枚举其他点是否在当前直线上。

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

参考代码:

void solve() {
	int n, K;
	cin >> n >> K;
	if (K == 1) {
		cout << "Infinity" << '\n';
		return;
	}
	vector<int>px(n), py(n);
	for (int i = 0; i < n; ++i) cin >> px[i] >> py[i];
	auto colinear = [&](int a, int b, int c) {
		long long val1 = (py[b] - py[a]) * (px[c] - px[a]);
		long long val2 = (px[b] - px[a]) * (py[c] - py[a]);
		return val1 == val2;
	};
	vector<vector<bool>>flag(n, vector<bool>(n, true));
	int res = 0, cnt = 0;
	vector<int>List;
	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			if (!flag[i][j]) continue;
			cnt = 2;
			List.clear();
			List.push_back(i);
			List.push_back(j);
			for (int k = j + 1; k < n; ++k) {
				if (!colinear(i, j, k)) continue;
				++cnt;
				List.push_back(k);
			}
			for (int p = 0; p < cnt; ++p)
				for (int q = p + 1; q < cnt; ++q) flag[List[p]][List[q]] = false;
			if (cnt >= K) ++res;
		}
	}
	cout << res << '\n';
	return;
}

posted @ 2022-04-21 19:37  cherish-lgb  阅读(171)  评论(0编辑  收藏  举报