AtCoder Beginner Contest 418


A - I'm a teapot

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::string s;
	std::cin >> s;
	if (n >= 3 && s.substr(n - 3) == "tea") {
		std::cout << "Yes\n";
	} else {
		std::cout << "No\n";
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

B - You're a teapot

枚举子串。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	std::string s;
	std::cin >> s;
	int n = s.size();

	auto get = [&](const std::string & s) -> double {
		int cnt = std::ranges::count(s, 't');
		return (cnt - 2) * 1.0 / ((int)s.size() - 2);
	};

	double ans = 0;
	for (int i = 0; i < n; ++ i) {
		for (int j = i + 2; j < n; ++ j) {
			if (s[i] == 't' && s[j] == 't') {
				ans = std::max(ans, get(s.substr(i, j - i + 1)));
			}
		}
	}

	std::cout << std::fixed << std::setprecision(12);
	std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}	

C - Flush

题意:第\(i\)个物品有\(a_i\)个,\(q\)次询问,每次给出一个\(b\),你需要求最小的\(x\),使得从所有物品中任意拿\(x\)个都有\(b\)个相同的。

\(a\)排序,预处理前缀和。
考虑最坏情况,记\(a_j\)为大于等于\(b\)的第一个位置,那么\(\sum_{i=1}^{j-1} a_i\)都选上也不会有\(b\)个相同的。然后大于等于\(j\)\(a_i\)都选出\(b-1\)个,此时不管再选哪一个都会有一个物品大于等于\(b\)个,所以答案是\(\sum_{i=1}^{j-1} a_i + (n - i + 1) \times (b - 1) + 1\)

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n, q;
	std::cin >> n >> q;
	std::vector<int> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	std::ranges::sort(a);
	std::vector<i64> sum(n + 1);
	for (int i = 0; i < n; ++ i) {
		sum[i + 1] = sum[i] + a[i];
	}

	while (q -- ) {
		int b;
		std::cin >> b;
		if (a.back() < b) {
			std::cout << -1 << "\n";
		} else {
			int p = std::ranges::lower_bound(a, b) - a.begin();
			i64 ans = sum[p] + (i64)(n - p) * (b - 1) + 1;
			std::cout << ans << "\n";
		}
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}	

D - XNOR Operation

题意:对于一个\(01\)串,每次可以选择相邻的两个元素,如果相同则用\(1\)替换它们,如果不同则用\(0\)替换它们,最终操作到只剩一个。如果一个\(01\)串可以最后剩下的是\(1\)则这个\(01\)串是好的。求\(s\)有多少子串是好的。

\(01, 10\)会变成\(0\)\(00\)会变成\(1\),发现每次操作\(0\)一定减少偶数个。那么想要最终留下\(1\),整个串里需要有偶数个\(0\)
记录前缀和的奇偶个数,累加就行。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::string s;
	std::cin >> s;
	int cnt[2]{1, 0};
	int sum = 0;
	i64 ans = 0;
	for (int i = 0; i < n; ++ i) {
		sum += s[i] == '0';
		ans += cnt[sum & 1];
		++ cnt[sum & 1];
	}

	std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}	

E - Trapezium

题意:求\(n\)个点里有多少梯形。保证没有三点共线。

把所有边拿出来,按极角排序,那么极角相同的边可以构成梯形。但发现平行四边形会被算两次,于是还需要减去平行四边形的数量。
接下来计算平行四边形个数,这是经典问题,平行四边形两个对角线的中点重合,那么可以用\(map\)记录每个点作为中点的个数,那么从中任意选两个就能组成一个平行四边形。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

using T = i64;

const T inf = 1e18;
const double eps = 0, PI = std::acos(-1);

struct Point {
	T x, y;
	Point(const T & _x = 0, const T & _y = 0) : x(_x), y(_y) {}
	Point operator + (const Point & p) const {
		return {x + p.x, y + p.y};
	}

	Point operator - (const Point & p) const {
		return {x - p.x, y - p.y};
	}

	Point operator * (const T & v) const {
		return {x * v, y * v};
	}

	Point operator / (const T & v) const {
		return {x / v, y / v};
	}

	friend Point operator * (const T & v, const Point & p) {
		return p * v;
	}

	Point & operator += (const Point & p) {
		x += p.x;
		y += p.y;
		return *this;
	}

	Point & operator -= (const Point & p) {
		x -= p.x;
		y -= p.y;
		return *this;
	}

	Point & operator *= (const T & v) {
		x *= v;
		y *= v;
		return *this;
	}

	Point & operator /= (const T & v) {
		x /= v;
		y /= v;
		return *this;
	}

	Point operator -() const {
		return Point(-x, -y);
	}
};

//叉乘
T cross(const Point & a, const Point & b) {
	return a.x * b.y - a.y * b.x;
}


//分类,极角排序用
int quad(const Point & a) {
	if (a.y < -eps) {
		return 1;
	}

	if (a.y > eps) {
		return 4;
	}

	if (a.x < -eps) {
		return 5;
	}

	if (a.x > eps) {
		return 3;
	}

	return 2;
}

//极角排序
struct argcmp {
	bool operator()(const Point & a, const Point & b) {
		int qa = quad(a), qb = quad(b);
		if (qa != qb) {
			return qa < qb;
		}

		auto t = cross(a, b);
		//如果相同极角还需要按极径排序
		// if (std::fabs(t) <= eps) {
		// 	return dot(a, a) < dot(b, b) - eps;
		// }
		return t > eps;
	}
};

void solve() {
	int n;
	std::cin >> n;
	std::vector<Point> p(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> p[i].x >> p[i].y;
		p[i] *= 2;
	}

	std::vector<Point> a;
	for (int i = 0; i < n; ++ i) {
		for (int j = 0; j < n; ++ j) {
			if (i != j) {
				a.push_back(p[i] - p[j]);
			}
		}
	}

	std::sort(a.begin(), a.end(), argcmp());

	i64 ans = 0;
	for (int i = 0; i < a.size(); ++ i) {
		int j = i;
		while (j + 1 < a.size() && cross(a[i], a[j + 1]) == 0) {
			++ j;
		}

		i64 t = j - i + 1;
		ans += t * (t - 1) / 2;
		i = j;
	}
	
	ans /= 2;
	std::map<std::pair<i64, i64>, int> cnt;
	for (int i = 0; i < n; ++ i) {
		for (int j = i + 1; j < n; ++ j) {
			Point o = (p[i] + p[j]) / 2;
			++ cnt[{o.x, o.y}];
		}
	}

	for (auto & [_, c] : cnt) {
		ans -= (i64)c * (c - 1) / 2;
	}
	std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}
posted @ 2025-08-09 21:40  maburb  阅读(326)  评论(0)    收藏  举报