T1: 邮票问题

我们应该尽可能地使用面值比较大的邮票,从而让选择的邮票数量尽可能少

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using std::cin;
using std::cout;
using std::vector;

int main() {
    int n;
    cin >> n;
    
    vector<int> a{20, 10, 5, 1};
    int ans = 0;
    rep(i, 4) {
        ans += n/a[i];
        n %= a[i];
    }
    
    cout << ans << '\n';
    
    return 0;
}

T2: 密码解锁

按题意模拟即可

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using std::cin;
using std::cout;
using std::vector;
using std::string;

int main() {
    string password;
    cin >> password;
    
    vector<int> t(11);
    t[3] = 1;
    for (int i = 4; i <= 10; ++i) {
        t[i] = 2*t[i-1];
    }
    
    int ans = 0;
    string s;
    int i = 1;
    while (cin>>s) {
        if (s == password) {
            break;
        }
        else {
            ans += t[i];
        }
        if (i == 10) {
            puts("Locked");
            return 0;
        }
        i++;
    }
    
    cout << ans << '\n';
    
    return 0;
}

T3:模糊匹配

模糊匹配的定义:

  • 长度相等
  • \(S[i]\)? 时,\(T[i]\) 任意,否则 \(S[i] == T[i]\)

还是模拟

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using std::cin;
using std::cout;
using std::string;

int main() {
    string s;
    cin >> s;
    
    int n;
    cin >> n;
    int ans = 0;
    while (n--) {
        string t;
        cin >> t;
        if (t.size() != s.size()) continue;
        bool match = true;
        rep(i, s.size()) {
            if (s[i] == '?') continue;
            else if (s[i] != t[i]) {
                match = false;
                break;
            }
        }
        if (match) ans++;
    }
    
    cout << ans << '\n';
    
    return 0;
}

T4: 连续的零

可以考虑从结果出发
假如我们最后得到了连续的 \(k\)\(0\),原本有 \(x\)\(0\)\(k-x\)\(1\)
至少改了 \(k-x\) 个地方 (从 \(1\) 变成 \(0\))
问的是 \(k-x\) 的最小值,这也就是 \(x\) 的最大值
于是我们可以在连续的 \(k\) 个数中找 \(x\) 的最大值
暴力的时间是 \(O(nk)\),显然超时

t[i] 表示连续的 \(k\) 个数中 \(0\) 的个数
注意到 \(t[i]\)\(t[i+1]\) 其实它们只有两个地方不一样,所以可以由 \(t[i]\) 推出 \(t[i+1]\)

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using std::cin;
using std::cout;
using std::max;
using std::string;
using std::vector;
using ll = long long;

int main() {
    int n, k;
    cin >> n >> k;
    
    string s;
    cin >> s;
    
    vector<int> t(n+1);
    rep(i, k) {
        if (s[i] == '0') t[k]++;
    }
    int mx = t[k];
    // t[i] -> t[i+1]
    for (int i = k; i < n; ++i) {
        int ni = i+1;
        t[ni] = t[i];
        if (s[i] == '0') t[ni]++;
        if (s[i-k] == '0') t[ni]--;
        mx = max(mx, t[ni]);
    }
    
    cout << k-mx << '\n';
    
    return 0;
}

T5:平整序列

本题是差分的经典应用
构造数组 \(b\) 满足 \(b[i] = a[i] - a[i-1]\)
每次选择一个正的 \(b[i]\) --,负的 \(b[j]\) ++,这一定是最快的

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)

using std::cin;
using std::cout;
using std::vector;
using ll = long long;

int main() {
    int n;
    cin >> n;
    
    vector<int> a(n+2);
    rep(i, n) cin >> a[i];
    
    ll ans = 0;
    vector<int> b(n+2);
    rep(i, n+1) {
        b[i] = a[i]-a[i-1];
        if (b[i] > 0) ans += b[i];
    }
    
    cout << ans << '\n';
    
    return 0;
}