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;
}