T1:Water Station

模拟

代码实现
// C++实现
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int ans = round(n/5.)*5;
cout << ans << '\n';
return 0;
}
// Python实现
n = int(input())
ans = int(round(n/5, 0))*5
print(ans)

T2:ABCDEFG

可以把边权挂在左边的点上,求一遍区间和即可

代码实现
#include <bits/stdc++.h>
using namespace std;
int main() {
char p, q;
cin >> p >> q;
vector<int> d = {3, 1, 4, 1, 5, 9};
if (p > q) swap(p, q);
p -= 'A'; q -= 'A';
int ans = 0;
for (int i = p; i < q; ++i) {
ans += d[i];
}
cout << ans << '\n';
return 0;
}

找出矩形所在的四个边界

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int h, w;
cin >> h >> w;
vector<string> s(h);
rep(i, h) cin >> s[i];
int li = h, lj = w, ri = 0, rj = 0;
rep(i, h)rep(j, w) {
if (s[i][j] == '#') {
li = min(li, i);
lj = min(lj, j);
ri = max(ri, i);
rj = max(rj, j);
}
}
for (int i = li; i <= ri; ++i) {
for (int j = lj; j <= rj; ++j) {
if (s[i][j] == '.') {
cout << i+1 << ' ' << j+1 << '\n';
}
}
}
return 0;
}

T4:Sleep Log

f(x) 表示前 x 分钟的睡眠睡觉,那么带求的答案就是 f(r)f(l)

先预处理出睡眠时间的前缀和 s
然后二分找到 x 所在时间段的左端点位置 i
最后 f(x) 就是 s[i] 加上剩余部分的睡眠时间
如何计算剩余部分的睡眠时间?

  • 如果 x 位于睡觉时间段,那么这一部分的贡献就是 xAi
  • 如果 x 位于不睡觉时间段,那么这一部分的贡献就是 0
代码实现
#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> a(n);
rep(i, n) cin >> a[i];
vector<int> s(n);
for (int i = 1; i < n; ++i) {
s[i] = s[i-1];
if (i%2 == 0) s[i] += a[i]-a[i-1];
}
auto f = [&](int x) {
int i = lower_bound(a.begin(), a.end(), x) - a.begin() - 1;
if (i < 0) return 0;
int res = s[i];
if (i%2 == 1) res += x-a[i];
return res;
};
int q;
cin >> q;
rep(qi, q) {
int l, r;
cin >> l >> r;
int ans = f(r)-f(l);
cout << ans << '\n';
}
return 0;
}

Dijkstra 的变种题
d[v] 表示点 v 处剩余体力的最大值
然后用 Dijkstra 求出每个点的 d[v] 即可
最后如果 d[v]0,则说明点 v 就是被保护的点

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using P = pair<int, int>;
int main() {
int n, m, k;
cin >> n >> m >> k;
vector<vector<int>> to(n);
rep(i, m) {
int a, b;
cin >> a >> b;
--a; --b;
to[a].push_back(b);
to[b].push_back(a);
}
vector<int> d(n, -1);
priority_queue<P> q;
rep(i, k) {
int p, h;
cin >> p >> h;
--p;
d[p] = h;
q.emplace(h, p);
}
while (q.size()) {
auto [h, v] = q.top(); q.pop();
if (d[v] != h) continue;
for (int u : to[v]) {
if (d[u] >= h-1) continue;
d[u] = h-1;
q.emplace(h-1, u);
}
}
vector<int> ans;
rep(i, n) if (d[i] >= 0) ans.push_back(i+1);
cout << ans.size() << '\n';
for (int v : ans) cout << v << ' ';
return 0;
}

T6:Dungeon Explore

dfs

为了不重复遍历同一个点,除了在死胡同中回头的时候,普通 dfs 可以在 2N 次以内实现。

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<bool> used(n+1);
vector<int> pre(n+1);
auto get = [&]() {
int k;
cin >> k;
vector<int> res(k);
rep(i, k) cin >> res[i];
return res;
};
int v = 1;
used[v] = true;
while (v != n) {
auto to = get();
int u = -1;
for (int x : to) {
if (!used[x]) u = x;
}
if (u == -1) u = pre[v];
else {
used[u] = true;
pre[u] = v;
}
cout << u << '\n';
v = u;
}
return 0;
}

T7:Banned Substrings

dp[i][s] 表示长度为 i 且最后的 5 个字符构成的子串为 s 时的合法字符串个数
由于转移不依赖于 i,所以可以用矩阵快速幂来优化!

时间复杂度为 O(logNM3)

代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using mint = modint998244353;
template<typename T>
struct Matrix {
int h, w;
vector<vector<T>> d;
Matrix() {}
Matrix(int h, int w, T val=0): h(h), w(w), d(h, vector<T>(w,val)) {}
Matrix& unit() {
assert(h == w);
rep(i,h) d[i][i] = 1;
return *this;
}
const vector<T>& operator[](int i) const { return d[i];}
vector<T>& operator[](int i) { return d[i];}
Matrix operator*(const Matrix& a) const {
assert(w == a.h);
Matrix r(h, a.w);
rep(i,h)rep(k,w)rep(j,a.w) {
r[i][j] += d[i][k]*a[k][j];
}
return r;
}
Matrix pow(long long t) const {
assert(h == w);
if (!t) return Matrix(h,h).unit();
if (t == 1) return *this;
Matrix r = pow(t>>1);
r = r*r;
if (t&1) r = r*(*this);
return r;
}
};
int main() {
ll n; int m;
cin >> n >> m;
vector<string> S(m);
rep(i, m) cin >> S[i];
auto check = [&](int t, int w) {
string ts;
rep(i, w) ts += 'a'+(t&1), t >>= 1;
reverse(ts.begin(), ts.end());
for (string s : S) {
if (ts.find(s) != string::npos) return false;
}
return true;
};
int l = 5, d = 1<<l;
if (n < l) {
int ans = 0;
rep(i, 1<<n) {
if (check(i, n)) ans++;
}
cout << ans << '\n';
return 0;
}
Matrix<mint> a(d, d), x(1, d);
rep(i, d) {
rep(c, 2) {
int j = (i<<1)|c;
if (!check(j, l+1)) continue;
j &= d-1;
a[i][j] += 1;
}
}
rep(i, d) {
if (check(i, l)) x[0][i] = 1;
}
x = x*a.pow(n-l);
mint ans;
rep(i, d) ans += x[0][i];
cout << ans.val() << '\n';
return 0;
}