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: 连续的零

可以考虑从结果出发
假如我们最后得到了连续的 k0,原本有 x0kx1
至少改了 kx 个地方 (从 1 变成 0)
问的是 kx 的最小值,这也就是 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[i1]
每次选择一个正的 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;
}