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\) 位于睡觉时间段,那么这一部分的贡献就是 \(x-A_i\)
  • 如果 \(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;
}

\(\operatorname{Dijkstra}\) 的变种题
d[v] 表示点 \(v\) 处剩余体力的最大值
然后用 \(\operatorname{Dijkstra}\) 求出每个点的 \(d[v]\) 即可
最后如果 \(d[v] \geqslant 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

\(\operatorname{dfs}\)

为了不重复遍历同一个点,除了在死胡同中回头的时候,普通 \(\operatorname{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\),所以可以用矩阵快速幂来优化!

时间复杂度为 \(\mathcal{O}(\log N \cdot M^3)\)

代码实现
#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;
}