Codeforces Round 991 (Div. 3) 题解 (A ~ G)

A. Line Breaks

模拟即可

#include <bits/stdc++.h>

void solve()
{
	int n, m; std::cin >> n >> m;
	std::vector<std::string> s(n);
	for(int i = 0; i < n; i++) std::cin >> s[i];
	for(int i = 0, j = 0; i < n; i++)
	{
		j += s[i].size();
		if(j > m)
		{
			std::cout << i << "\n";
			return;
		}
	}
	std::cout << n << "\n";
}

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}

B. Transfusion

每次操作都是间隔 \(2\),所以分奇偶考虑,奇偶的平均值相等即可

#include <bits/stdc++.h>

using i64 = long long;

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

	i64 odd = 0, even = 0;
	for(int i = 0; i < n; i++)
	{
		if(i & 1) odd += a[i];
		else even += a[i];
	}

	int x = n / 2, y = x + (n % 2);
	if(odd % x || even % y) 
	{
		std::cout << "NO\n";
		return;
	}
	if(odd / x == even / y) std::cout << "YES\n";
	else std::cout << "NO\n";
}

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}

C. Uninteresting Number

最后能被 \(9\) 整除的条件是数位和能被 \(9\) 整除,所以可以考虑对模 \(9\) 的余数进行一个可达性 \(dp\)

#include <bits/stdc++.h>

using i64 = long long;

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

	std::vector<int> f(9);
	f[(s[0] - '0') % 9] = 1;
	if((s[0] - '0') * (s[0] - '0') < 10) f[(s[0] - '0') * (s[0] - '0') % 9] = 1;

	for(int i = 1; i < n; i++)
	{
		std::vector<int> g(9);
		int x = s[i] - '0';
		for(int j = 0; j < 9; j++)
		{
			g[(j + x) % 9] |= f[j];
			if(x * x < 10) g[(j + x * x) % 9] |= f[j];
		}
		std::swap(f, g);
	}

	if(f[0]) std::cout << "YES\n";
	else std::cout << "NO\n";
}

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}

D. Digital string maximization

因为每次移位都要减一,所以最多只会把当前为往后九位的数交换过来,所以我们直接枚举每一位,贪心的让这一位的数最大即可

#include <bits/stdc++.h>

using i64 = long long;

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

	for(int i = 0; i < n; i++)
	{
		int pos = i, max = s[i] - '0';
		for(int j = i + 1; j < std::min(n, i + 9); j++)
		{
			if((s[j] - '0') - (j - i) > max)
			{
				pos = j;
				max = (s[j] - '0') - (j - i);
			}
		}

		char tmp = max + '0';
		for(int j = pos; j > i; j--) std::swap(s[j], s[j - 1]);
		s[i] = tmp;
	}

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

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}

E. Three Strings

考虑 \(dp\),设 \(f[i][j]\) 为考虑到 \(a\) 的第 \(i\) 位和 \(b\) 的第 \(j\) 位时最大匹配长度,不难得到转移

\[f[i+1][j]=max(f[i+1][j],f[i][j]+1),\ a[i]=c[i+j] \\ f[i][j+1]=max(f[i][j+1],f[i][j]+1),\ b[i]=c[i+j] \notag \]

#include <bits/stdc++.h>

using i64 = long long;

void solve()
{
	std::string a, b, c; std::cin >> a >> b >> c;
	int lena = a.size(), lenb = b.size(), lenc = c.size();

	std::vector f(lena + 1, std::vector<int>(lenb + 1));
	for(int i = 0; i <= lena; i++)
	{
		for(int j = 0; j <= lenb; j++)
		{
			if(i < lena) f[i + 1][j] = std::max(f[i + 1][j], f[i][j]);
			if(j < lenb) f[i][j + 1] = std::max(f[i][j + 1], f[i][j]);
			
			if(i < lena && a[i] == c[i + j])
				f[i + 1][j] = std::max(f[i + 1][j], f[i][j] + 1);
			if(j < lenb && b[j] == c[i + j])
				f[i][j + 1] = std::max(f[i][j + 1], f[i][j] + 1);
		}
	}

	std::cout << lenc - f[lena][lenb] << "\n";
}

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}

F. Maximum modulo equality

首先,如果 \(a_l\ mod\ m = a_{l+1}\ mod\ m = ... = a_{r}\ mod\ m\),说明 \(a_l,a_{l+1},...,a_r\) 在同一个等差数列里,所以最大的 \(m\) 就是这一段区间差分之后的 \(gcd\)

注意特判 \(l=r\) 的情况

#include <bits/stdc++.h>

using i64 = long long;

template<class T>
struct ST
{
	std::vector<std::vector<T>> f;

	ST(std::vector<T> &a)
	{
		int n = a.size(), logn = std::__lg(n);
		f.assign(n, std::vector<int>(logn + 1));

		for(int i = 0; i < n; i++) f[i][0] = a[i];
		for(int j = 0; j < logn; j++)
			for(int i = 0; i + (1 << (j + 1)) - 1 < n; i++)
				f[i][j + 1] = std::gcd(f[i][j], f[i + (1 << j)][j]);
	}

	T operator()(int l, int r)
	{
		int log = std::__lg(r - l);
		return std::gcd(f[l][log], f[r - (1 << log)][log]);
	}
};

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::vector<int> b(n - 1);
	for(int i = 0; i + 1 < n; i++) b[i] = std::abs(a[i] - a[i + 1]);

	ST<int> st(b);
	for(int i = 0; i < q; i++)
	{
		int l, r; std::cin >> l >> r;
		l--, r--;
		if(l == r)
		{
			std::cout << 0 << " \n"[i == q - 1];
			continue;
		}
		std::cout << st(l, r) << " \n"[i == q - 1];
	}
}

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}

G. Tree Destruction

考虑 \(dp\),记 \(f[0][x]\) 为以 \(x\) 为根的子树的答案,并且 \(x\) 不被删除;\(f[1][x]\) 为以 \(x\) 为根的子树的答案,并且 \(x\) 被删除,同时 \(x\) 的儿子最多被删除一个;\(f[2][x]\) 为以 \(x\) 为根的子树,并且 \(x\) 有两个儿子被删除。考虑转移:

\[\begin{align} f[0][x]=&max_{y \in son(x)}(f[0][x],f[1][y] + 1) \notag \\ f[1][x]=&max_{y \in son(x)}(f[1][x],f[1][y] + size(x)-1) \notag \\ f[2][x]=&max_{y1,y2 \in son(x)}\{f[1][y1]+f[1][y2]+size(x)-2\} \notag \end{align} \]

#include <bits/stdc++.h>

using i64 = long long;

void solve()
{
	int n; std::cin >> n;
	std::vector<std::vector<int>> adj(n);
	for(int i = 1; i < n; i++) 
	{
		int u, v; std::cin >> u >> v;
		u--, v--;
		adj[u].emplace_back(v);
		adj[v].emplace_back(u);
	}

	std::vector f(3, std::vector<int>(n));
	int ans = 0;
	auto dfs = [&](auto dfs, int x, int fa) -> void
	{
		std::array<int, 2> max{};
		f[0][x] = 1, f[1][x] = adj[x].size() - 1 + (fa == -1);
		for(auto y : adj[x])
		{
			if(y == fa) continue;

			dfs(dfs, y, x);
			max[1] = std::max(max[1], f[1][y]);
			if(max[1] > max[0]) std::swap(max[0], max[1]);
			f[0][x] = std::max(f[0][x], f[1][y] + 1);
			f[1][x] = std::max(f[1][x], f[1][y] + (int)adj[x].size() - 2 + (fa == -1));
		}

		if(adj[x].size() + (fa == -1) >= 3) ans = std::max(ans, max[0] + max[1] + (int)adj[x].size() - 2);
	};	
	dfs(dfs, 0, -1);

	ans = std::max({ans, f[0][i], f[1][i]});
	std::cout << ans << "\n";
}

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

	int t; std::cin >> t;
	while(t--) solve();

	return 0;
}
posted @ 2024-12-06 01:05  Repeater11  阅读(115)  评论(1编辑  收藏  举报