SMU winter 2025 Personal Round 2

SMU winter 2025 Personal Round 2

A. Ichihime and Triangle

思路

\(a, b, c, d\) 单调递增,所以 \(x, y, z\) 也会单调递增。这时只需要满足 \(x + y > z\) 就行了。

我们把 \(x, y\) 取最大值:\(x = b\), \(y = c\)\(z\) 取最小值:\(z = c\)。就是最有可能实现的方案。

这时我们发现 \(x + y > z\),说明一定能实现。所以直接输出 \(b,c, c\) 即可。

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

	int a, b, c, d;
	cin >> a >> b >> c >> d;

	cout << b << " " << c << " " << c << "\n";

}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

B - Kana and Dragon Quest game

思路

对第一种操作,当 \(x > 20\) 时,该操作会一直减小 \(x\)

所以当 \(x > 20\) 时,我们可以一直执行第一种操作,然后再执行第二种操作,这样能尽可能的减少 \(x\)

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

	int x, n, m;
	cin >> x >> n >> m;

	while (x > 20 && n) {
		n --;
		x = x / 2 + 10;
	}

	cout << (x > m * 10 ? "NO\n" : "YES\n");

}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

C - Linova and Kingdom

思路

建立好树,令1号节点的深度是1,然后往下走,当遍历到的点是叶子节点时,该点的贡献是该点到1号节点的距离(\(deep-1\)),当该点不是叶子节点时该点的贡献是\(deep-cnt\)\(cnt\)为算上自己和自己所有子子孙孙且都认为是工业节点的数量)。

这样得到的数组按贡献降序排序,并将前\(k\)个贡献累加即可。

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, k;
	cin >> n >> k;

	vector g(n + 1, vector<int>());
	for (int i = 1; i < n; i ++) {
		int u, v;
		cin >> u >> v;
		g[u].emplace_back(v);
		g[v].emplace_back(u);
	}

	vector<int> dep(n + 1), has(n + 1);
	auto dfs = [&](auto && self, int u, int fa)->void{
		dep[u] = dep[fa] + 1;
		has[u] = 1;
		for (auto &v : g[u]) {
			if (v == fa) continue;
			self(self, v, u);
			has[u] += has[v];
		}
	};

	dfs(dfs, 1, 0);

	vector<int> a(n + 1);
	iota(a.begin(), a.end(), 0);

	sort(a.begin() + 1, a.end(), [&](auto x, auto y) {
		return dep[x] - has[x] > dep[y] - has[y];
	});

	i64 ans = 0;
	for (int i = 1; i <= k; i ++) {
		ans += dep[a[i]] - has[a[i]];
	}

	cout << ans << "\n";

	return 0;
}

D - Xenia and Colorful Gems

思路

先枚举其中一个,然后二分找到距离该点较近的几个数,得到两个数后,便可以得知第三个数的范围,在此基础上再去进行二分,然后枚举计算最小值即可。

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

	int n[3] {};
	for (int i : {0, 1, 2}) {
		cin >> n[i];
	}

	vector has(3, vector<int>());
	for (int i : {0, 1, 2}) {
		has[i].resize(n[i]);
		for (auto &x : has[i]) {
			cin >> x;
		}
		sort(has[i].begin(), has[i].end());
	}

	i64 ans = LLONG_MAX;
	auto ck = [&](int idx)->void{
		for (auto &x : has[idx]) {
			int ny = lower_bound(has[(idx + 1) % 3].begin(), has[(idx + 1) % 3].end(), x) - has[(idx + 1) % 3].begin();
			for (int i = max(0, ny - 5); i < min(n[(idx + 1) % 3], ny + 6); i ++) {
				i64 y = has[(idx + 1) % 3][i];
				int nz = lower_bound(has[(idx + 2) % 3].begin(), has[(idx + 2) % 3].end(), (x + y) / 2) - has[(idx + 2) % 3].begin();
				for (int j = max(0, nz - 5); j < min(n[(idx + 2) % 3], nz + 6); j ++) {
					i64 z = has[(idx + 2) % 3][j];
					ans = min(ans, (x - y) * (x - y) + (x - z) * (x - z) + (y - z) * (y - z));
				}
			}
		}
	};

	ck(0);
	ck(1);
	ck(2);

	cout << ans << "\n";

}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

E - Kaavi and Magic Spell

思路

动态规划,定义状态 \(dp[i][j]\) 表示使用 \(S\) 的前 \(j-i+1\) 个字符构造的字符串恰好覆盖 \(T\) 的第 \(i\)\(j\) 位时的方案数。初始时,若 \(S\) 的第一个字符与 \(T\) 的第 \(k\) 位匹配(或 \(k > m\)),则 \(dp[k][k] = 2\)(两种操作方式)。

对于长度为 \(len\) 的子问题,若当前字符 \(s[len]\) 添加到前端且与 \(T[i]\) 匹配(或 \(i > m\)),则从 \(dp[i+1][j]\) 转移;若添加到后端且与 \(T[j]\) 匹配(或 \(j > m\)),则从 \(dp[i][j-1]\) 转移。最终答案为所有满足 \(1 \leq i \leq j \leq n\)\(j \geq m\)\(dp[1][j]\) 之和。时间复杂度为 \(O(n^2)\),空间复杂度 \(O(n^2)\)

代码

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

//------取模机------//
using i64 = long long;
template<class T>
constexpr T power(T a, i64 b) {
	T res {1};
	for (; b; b /= 2, a *= a) {
		if (b % 2) {
			res *= a;
		}
	}
	return res;
} // 快速幂

constexpr i64 mul(i64 a, i64 b, i64 p) {
	i64 res = a * b - i64(1.L * a * b / p) * p;
	res %= p;
	if (res < 0) {
		res += p;
	}
	return res;
} // 取模乘

template<i64 P>
struct MInt {
	i64 x;
	constexpr MInt() : x {0} {}
	constexpr MInt(i64 x) : x {norm(x % getMod())} {}

	static i64 Mod;
	constexpr static i64 getMod() {
		if (P > 0) {
			return P;
		} else {
			return Mod;
		}
	}
	constexpr static void setMod(i64 Mod_) {
		Mod = Mod_;
	}//只有P<=0, setMod才生效
	constexpr i64 norm(i64 x) const {
		if (x < 0) {
			x += getMod();
		}
		if (x >= getMod()) {
			x -= getMod();
		}
		return x;
	}
	constexpr i64 val() const {
		return x;
	}
	constexpr MInt operator-() const {
		MInt res;
		res.x = norm(getMod() - x);
		return res;
	}
	constexpr MInt inv() const {
		return power(*this, getMod() - 2);
	}
	constexpr MInt &operator*=(MInt rhs) & {
		if (getMod() < (1ULL << 31)) {
			x = x * rhs.x % int(getMod());
		} else {
			x = mul(x, rhs.x, getMod());
		}
		return *this;
	}
	constexpr MInt &operator+=(MInt rhs) & {
		x = norm(x + rhs.x);
		return *this;
	}
	constexpr MInt &operator-=(MInt rhs) & {
		x = norm(x - rhs.x);
		return *this;
	}
	constexpr MInt &operator/=(MInt rhs) & {
		return *this *= rhs.inv();
	}
	friend constexpr MInt operator*(MInt lhs, MInt rhs) {
		MInt res = lhs;
		res *= rhs;
		return res;
	}
	friend constexpr MInt operator+(MInt lhs, MInt rhs) {
		MInt res = lhs;
		res += rhs;
		return res;
	}
	friend constexpr MInt operator-(MInt lhs, MInt rhs) {
		MInt res = lhs;
		res -= rhs;
		return res;
	}
	friend constexpr MInt operator/(MInt lhs, MInt rhs) {
		MInt res = lhs;
		res /= rhs;
		return res;
	}
	friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
		i64 v;
		is >> v;
		a = MInt(v);
		return is;
	}
	friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
		return os << a.val();
	}
	friend constexpr bool operator==(MInt lhs, MInt rhs) {
		return lhs.val() == rhs.val();
	}
	friend constexpr bool operator!=(MInt lhs, MInt rhs) {
		return lhs.val() != rhs.val();
	}
	friend constexpr bool operator<(MInt lhs, MInt rhs) {
		return lhs.val() < rhs.val();
	}
};

constexpr int MOD[] = {998244353, 1000000007};
using Z = MInt<MOD[0]>;
//------取模机------//

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	string s, t;
	cin >> s >> t;

	int n = s.size(), m = t.size();
	vector dp(n + 1, vector<Z>(n + 1));

	s = " " + s, t = " " + t;
	for (int i = 1; i <= n; i ++) {
		if (i > m || s[1] == t[i]) {
			dp[i][i] = 2;
		}
	}

	for (int len = 2; len <= n; len ++) {
		for (int i = 1; i + len - 1 <= n; i ++) {
			int j = i + len - 1;
			if (i > m || s[len] == t[i]) {
				dp[i][j] += dp[i + 1][j];
			}
			if (j > m || s[len] == t[j]) {
				dp[i][j] += dp[i][j - 1];
			}
		}
	}

	Z ans = 0;
	for (int i = m; i <= n; i ++) {
		ans += dp[1][i];
	}

	cout << ans << "\n";

	return 0;
}
posted @ 2025-02-09 19:10  Ke_scholar  阅读(18)  评论(0)    收藏  举报