[补题记录] Atcoder Beginner Contest 312(A~E)

URL:https://atcoder.jp/contests/abc312

目录

A

Problem/题意

Thought/思路

Code/代码

B

Problem/题意

Thought/思路

Code/代码

C

Problem/题意

Thought/思路

Code/代码

D

Problem/题意

Thought/思路

Code/代码

E

Problem/题意

Thought/思路

Code/代码


A

Problem/题意

Thought/思路

模拟。 

Code/代码

#include "bits/stdc++.h"

signed main() <%
	std::string s<:10:> = <%"ACE", "BDF", "CEG", "DFA", "EGB", "FAC", "GBD"%>;
	std::string x; std::cin >> x;
	for (int i = 0; i < 7; ++ i) {
		if (x == s<:i:>) {
			std::cout << "Yes";
			return 0;
		}
	}
	std::cout << "No";
	return 0;
%>

B

Problem/题意

对于一个 9 * 9 的矩阵,左上角要求是一个 3 * 3 的黑矩阵,右下角也是一个 3 * 3 的黑矩阵,且他们的边缘要求是白色的。

Thought/思路

模拟。

Code/代码

#include "bits/stdc++.h"

int n, m;
char mp<:107:><:107:>;
char m1<:6:><:6:> = {
	"###.",
	"###.",
	"###.",
	"...."
};
char m2<:6:><:6:> = {
	"....",
	".###",
	".###",
	".###"
};

bool check(int x, int y) {
	//std::cout << "=======\n";
	bool res = true;
	for (int i = 0; i <= 3; ++ i) {
		for (int j = 0; j <= 3; ++ j) {
			//std::cout << m1[i][j] << " " << mp[x + i][y + j] << "\n";
			if (m1[i][j] != mp[x + i][y + j]) res = false;
		}
	}
	//std::cout << "--------\n";
	for (int i = 0; i <= 3; ++ i) {
		for (int j = 0; j <= 3; ++ j) {
			//std::cout << m2[i][j] << " " << mp[x + i][y + j] << "\n";
			if (m2[i][j] != mp[x + i + 5][y + j + 5]) res = false;
		}
	}
	//std::cout << "=======\n";
	return res;
}

signed main() <%
	std::cin >> n >> m;
	for (int i = 1; i <= n; ++ i) <%
		for (int j = 1; j <= m; ++ j) <%
			std::cin >> mp<:i:><:j:>;
		%>
	%>
	for (int i = 1; i <= n - 8; ++ i) <%
		for (int j = 1; j <= m - 8; ++ j) <%
			if (check(i, j)) {
				std::cout << i << " " << j << "\n";
			}
		%>
	%>
%>

C

Problem/题意

有 N 个卖家,他们出售苹果的最低售价是 Ai。

有 M 个买家,他们购买苹果的最高预期是 Bi。

求一个最小的 X,使得能出这个价格的卖家数量大于等于能出这个价格的买家数量。

Thought/思路

二分 X。

Code/代码

#include "bits/stdc++.h"

int n, m, a[200007], b[200007];

bool check(int x) {
	int num_a = 0, num_b = 0;
	for (int i = 1; i <= n; ++ i) if (a[i] <= x) num_a ++;
	for (int i = 1; i <= m; ++ i) if (b[i] >= x) num_b ++;
	if (num_a >= num_b) return true;
	else return false;
}

signed main() {
	std::cin >> n >> m;
	for (int i = 1; i <= n; ++ i) std::cin >> a[i];
	for (int j = 1; j <= m; ++ j) std::cin >> b[j];
	int l = 0, r = 1e9 + 7;
	while (l + 1 != r) {
		int mid = (l + r) >> 1;
		if (check(mid)) r = mid;
		else l = mid;
	}
	std::cout << r;
}

D

Problem/题意

给一个由()?组成的字符串,将?转换为()后能有多少种合法方案。

Thought/思路

合法的括号序列显然要满足,左到右的每个位置,(的数量不少于)的数量,且最后两者数量相等

基于此,我们定义 dp[i][j] 为,前 i 个字符中,左括号数量为 j 个的合法方案数。

当 s[i] = '(' 时,可以直接转移;

当 s[i] = ')' 时,需要判断当前的左括号数量是否大于等于右括号数量。

最后就是输出 dp[n][n / 2]。

Code/代码

#include "bits/stdc++.h"

const int mod = 998244353;

int dp[3007][3007];

signed main() {
	std::string s; std::cin >> s;
	int n = s.length();

	dp[0][0] = 1;
	s = "#" + s;
	for (int i = 1; i <= n; ++ i) {
		for (int j = 1; j <= i; ++ j) {
			if (s[i] == '(') {
				dp[i][j] = dp[i - 1][j - 1];
			} else if (s[i] == ')') {
				if (j >= i - j) dp[i][j] = dp[i - 1][j];
			} else {
				dp[i][j] = dp[i - 1][j - 1];
				if (j >= i - j) dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
			}
		}
	}

	std::cout << dp[n][n / 2] % mod;
}

E

Problem/题意

给定 n 个没有相交的正方体,对于每个正方体,问它与多少个正方体会有面的相切。

Thought/思路

不会,这是别人的思路(取自~Lanly~): 

Code/代码

#include "bits/stdc++.h"

int n, to[107][107][107];

signed main() {
	std::cin >> n;
	for (int i = 1; i <= n; ++ i) {
		std::array <int, 6> p;
		for (auto &j : p) std::cin >> j;

		for (int x = p[0]; x < p[3]; ++ x) {
			for (int y = p[1]; y < p[4]; ++ y) {
				for (int z = p[2]; z < p[5]; ++ z) {
					to[x][y][z] = i;
				}
			}
		}
	}

	std::vector <std::set <int>> st(n + 1);
	for (int i = 0; i < 100; ++ i) {
		for (int j = 0; j < 100; ++ j) {
			for (int k = 0; k < 100; ++ k) {
				int o = to[i][j][k];
				int a = to[i + 1][j][k], b = to[i][j + 1][k], c = to[i][j][k + 1];

				if (o == 0) continue;
				if (a and a != o) {
					st[o].insert(a);
					st[a].insert(o);
				}
				if (b and b != o) {
					st[o].insert(b);
					st[b].insert(o);
				}
				if (c and c != o) {
					st[o].insert(c);
					st[c].insert(o);
				}
			}
		}
	}

	for (int i = 1; i <= n; ++ i) std::cout << st[i].size() << "\n";
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值