ABC447CDE、ABC448C、DMY51D题解
~ 2026-3-15 16:37:12
abc447_c
给你由大写英文字母组成的字符串 和 。
您可以按任意顺序执行以下两种类型的运算任意次数(可能为零):
- 在 的任意位置(可能是开头或结尾)插入一个字符
A。 - 在 中选择一个字符
A并删除。其余字符按原来的顺序连接。
判断是否有可能使 等于 ,如果有可能,求所需运算的最小总数。
https://atcoder.jp/contests/abc447/tasks/abc447_c
abc447_d
可以在一个字符串中删除一个子序列 ABC,问最多可以删除几次
https://atcoder.jp/contests/abc447/tasks/abc447_d
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
cin>>s;
int a=0,ab=0,abc=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='A')
a++;
if(s[i]=='B'&&a!=0)
a--,ab++;
if(s[i]=='C'&&ab!=0)
ab--,abc++;
}
cout<<abc;
return 0;
}
abc447_e
给你一个简单相连的无向图 ,其中有 个顶点和 条边。这里是 。顶点的编号为 至 ,边的编号为 至 ;每条边都有一个称为成本的值,边 的成本为 。
现在,您要删除 中的一些边,这样 的连通部分的数目就会正好变为 。可以证明,在本问题的约束条件下,这总是可以实现的。
求删除的边的成本总和的最小值,模数为 。
https://atcoder.jp/contests/abc447/tasks/abc447_e
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
int two[200000 + 5];
int n, m;
int u[200000 + 5], v[200000 + 5];
// 并查集
int fa[200000 + 5];
int findRoot(int x)
{
if (x == fa[x])
return x;
return fa[x] = findRoot(fa[x]);
}
int main()
{
two[0] = 1;
for (int i = 1; i <= 200000; i++)
two[i] = two[i - 1] * 2 % MOD;
cin >> n >> m;
for (int i = 1; i <= m; i++)
cin >> u[i] >> v[i];
for (int i = 1; i <= n; i++)
fa[i] = i;
int num = n; // 联通块数量
int ans = 0;
for (int i = m; i >= 1; i--)
{
int rootU = findRoot[u[i]];
int rootV = findRoot[v[i]];
if (num == 2 && rootU != rootV)
{
ans = (ans + two[i]) % MOD;
continue;
}
// 添加这条边
if (rootU != rootV)
{
fa[rootU] = rootV;
num--;
}
}
cout << ans;
}
abc448_c
个数 。 次询问。
每次需要求出去掉 个数后,剩下数的最小值。
https://atcoder.jp/contests/abc448/tasks/abc448_c
#include <bits/stdc++.h>
using namespace std;
int n, k, Q;
int a[300000 + 5];
int b[6];
int id[300000 + 5];
bool cmp(int x, int y)
{
return a[x] < a[y];
}
void work()
{
for (int i = 1; i <= n; i++)
{
int now = id[i]; // 当前需要判断是否被删除了的下标
bool flag = true;
for (int j = 1; j <= k; j++)
if (now == b[j])
flag = false;
if (flag)
{
cout << a[now] << "\n";
return;
}
}
}
int main()
{
cin >> n >> Q;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
id[i] = i;
sort(id + 1, id + n + 1, cmp);
while (Q--)
{
cin >> k;
for (int i = 1; i <= k; i++)
cin >> b[i];
work();
}
}
代码源 R51D
https://bs.daimayuan.top/p/318
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 998244353;
int lcm(int a, int b)
{
return a / __gcd(a, b) * b;
}
int n, ans;
// d[1]~d[tot] 都是 n 的因子
int tot, d[1000 + 5];
void dfs(int now, int L)
{
if (L > n)
return;
if (now == tot + 1)
{
if (L == n)
ans++;
return;
}
dfs(now + 1, L);
dfs(now + 1, lcm(L, d[now]));
}
signed main()
{
cin >> n;
tot = 0;
for (int i = 1; i * i <= n; i++)
{
if (n % i != 0)
continue;
d[++tot] = i;
if (n / i != i)
d[++tot] = n / i;
}
ans = 0;
dfs(1, 1);
cout << ans;
}
dp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 998244353;
int n, ans;
int two[1500 + 5];
// lcm 恰好为 i 有 f(i) 种方案
map<int, int> book;
int f(int x)
{
if (book[x] != 0)
return book[x];
if (x == 1)
return book[x] = 1;
int cnt = 2;
int ans = 0;
for (int i = 2; i * i <= x; i++)
{
if (x % i != 0)
continue;
cnt++;
ans = (ans - f(i)) % MOD;
if (x / i != i)
{
cnt++;
ans = (ans - f(x / i)) % MOD;
}
}
ans = (ans - 1) % MOD; // -f(1)
ans = (ans + two[cnt] - 1) % MOD;
return book[x] = ans;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
two[0] = 1;
for (int i = 1; i <= 1500; i++)
two[i] = two[i - 1] * 2 % MOD;
cin >> n;
cout << (f(n) + MOD) % MOD;
return 0;
}
我们会审查剪贴板内容,并对发布不合适内容的同学进行相应的处理