T1: tcdr
模拟
代码实现
#include <bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
erase_if(s, [](char c) { return ranges::count("aeiou", c); });
cout << s << '\n';
return 0;
}
T2:The Middle Day
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<int> d(n);
rep(i, n) cin >> d[i];
int tot = reduce(d.begin(), d.end());
int k = (tot+1)/2;
rep(i, n) {
if (k <= d[i]) {
cout << i+1 << ' ' << k << '\n';
break;
}
k -= d[i];
}
return 0;
}
T3:Flavors
显然必选最美味的冰激凌,然后枚举另一个即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<int> f(n), s(n);
rep(i, n) cin >> f[i] >> s[i];
int a = 0, ai = -1;
rep(i, n) {
if (a < s[i]) {
a = s[i];
ai = i;
}
}
int b = 0;
rep(i, n) {
if (i == ai) continue;
if (f[i] == f[ai]) b = max(b, s[i]/2);
else b = max(b, s[i]);
}
int ans = a+b;
cout << ans << '\n';
return 0;
}
T4:Magical Cookies
维护每个字符在当前行/当前列中都出现了多少次,并在每次操作中进行更新,每次检查的复杂度就是 \(\mathcal{O}(26(H+W))\)
注意:只有剩下的某行/某列的曲奇颜色都相同,才执行删除操作
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int h, w;
cin >> h >> w;
vector<string> c(h);
rep(i, h) cin >> c[i];
vector a(h, vector<int>(w));
rep(i, h)rep(j, w) a[i][j] = c[i][j]-'a';
const int m = 26;
vector row(h, vector<int>(m));
vector col(w, vector<int>(m));
rep(i, h)rep(j, w) {
row[i][a[i][j]]++;
col[j][a[i][j]]++;
}
vector<bool> row_deleted(h);
vector<bool> col_deleted(w);
auto toDelete = [&](vector<int> x) {
int tot = 0, k = 0;
rep(j, m) {
tot += x[j];
if (x[j]) k++;
}
return tot >= 2 and k == 1;
};
auto del = [&](int i, int j) {
if (row_deleted[i] or col_deleted[j]) return;
row[i][a[i][j]]--;
col[j][a[i][j]]--;
};
bool upd = true;
while (upd) {
upd = false;
vector<int> del_row, del_col;
rep(i, h) {
if (row_deleted[i]) continue;
if (toDelete(row[i])) del_row.push_back(i);
}
rep(j, w) {
if (col_deleted[j]) continue;
if (toDelete(col[j])) del_col.push_back(j);
}
for (int i : del_row) {
rep(j, w) del(i, j);
row_deleted[i] = true;
upd = true;
}
for (int j : del_col) {
rep(i, h) del(i, j);
col_deleted[j] = true;
upd = true;
}
}
int ans = 0;
rep(i, h)rep(j, w) {
if (row_deleted[i] or col_deleted[j]) continue;
ans++;
}
cout << ans << '\n';
return 0;
}
T5:Prerequisites
\(\operatorname{dfs}\)
突然开始读第一本书,如果有不明白的地方就回到上一本书
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
cin >> n;
vector<vector<int>> to(n);
rep(i, n) {
int c;
cin >> c;
rep(j, c) {
int p;
cin >> p;
to[i].push_back(p-1);
}
}
vector<int> ans;
vector<bool> used(n);
auto dfs = [&](auto f, int v) -> void {
used[v] = true;
for (int u : to[v]) {
if (used[u]) continue;
f(f, u);
}
ans.push_back(v);
};
dfs(dfs, 0);
ans.pop_back();
for (int v : ans) cout << v+1 << ' ';
return 0;
}
T6:Shortcuts
记 dp[i][j]
表示到达检查点 \(i\) 处已经跳过 \(j\) 个检查点的最小移动距离
但时间复杂度是 \(\mathcal{O}(n^3)\)
即使通过所有的检查点,距离也只有 \(3 \times 10^8\),所以考虑罚款比这个更大的情况是没有用的!也就是说,只需考虑跳过的检查点不超过 \(20\) 个时,可以在 \(\mathcal{O}(20^2 n)\) 时间内解决!
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
inline void chmin(double& a, double b) { if (a > b) a = b; }
int main() {
int n;
cin >> n;
vector<int> x(n), y(n);
rep(i, n) cin >> x[i] >> y[i];
const int m = 20;
auto dist = [&](int i, int j) {
int dx = x[i]-x[j], dy = y[i]-y[j];
return sqrt(dx*dx+dy*dy);
};
const double INF = 1e18;
vector dp(n, vector<double>(m, INF));
dp[0][0] = 0;
rep(i, n)rep(j, m) {
for (int ni = i+1, nj = j; ni < n and nj < m; ++ni, ++nj) {
chmin(dp[ni][nj], dp[i][j]+dist(i, ni));
}
}
double ans = INF;
rep(j, m) chmin(ans, dp[n-1][j]+(1<<j>>1));
printf("%.10f\n", ans);
return 0;
}
T7:Ai + Bj + Ck = X (1 <= i, j, k <= N)
可以枚举 \(k\),然后就变成了求满足 \(Ai+Bj=Y\) 的解 \((i, j)\) 的个数的问题,而这个问题是 \(\operatorname{exgcd}\) 板题
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
// ai+bj=g
ll exgcd(ll a, ll b, ll& i, ll& j) {
if (b == 0) { i = 1; j = 0; return a; }
ll p = a/b, g = exgcd(b, a-b*p, j, i);
j -= p*i;
return g;
}
int main() {
int n;
cin >> n;
ll A, B, C, X;
cin >> A >> B >> C >> X;
X -= A+B+C;
auto f2 = [&](ll x) -> ll {
if (x < 0) return 0;
ll i, j;
ll g = exgcd(A, B, i, j);
if (x%g) return 0;
x /= g;
ll a = A/g, b = B/g;
// ai+bj=1
i = (i+b)*(x%b)%b;
j = (x-i*a)/b;
// a(i+bk)+b(j+ak)=x
// 0 <= i+bk, 0 <= j-ak (0 <= i < b)
// -i/b <= k <= j/a (-1 < -i/b <= 0)
if (j < 0) return 0;
return j/a+1;
};
auto f = [&](ll x) {
ll res = f2(x);
res -= f2(x-A*n);
res -= f2(x-B*n);
res += f2(x-A*n-B*n);
return res;
};
ll ans = 0;
rep(k, n) {
ans += f(X);
X -= C;
}
cout << ans << '\n';
return 0;
}