T1:Print 341
模拟
代码实现
n = int(input())
print('1'+'01'*n)
T2:Foreign Exchange
模拟
代码实现
n = int(input())
a = list(map(int, input().split()))
for i in range(n-1):
s, t = map(int, input().split())
x = a[i]//s
a[i+1] += t*x
print(a[-1])
T3:Takahashi Gets Lost
暴搜
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int h, w, n;
cin >> h >> w >> n;
string t;
cin >> t;
vector<string> s(h);
rep(i, h) cin >> s[i];
int ans = 0;
rep(si, h)rep(sj, w) {
if (s[si][sj] == '#') continue;
bool ok = true;
int i = si, j = sj;
for (char c : t) {
if (c == 'L') j--;
if (c == 'R') j++;
if (c == 'U') i--;
if (c == 'D') i++;
if (s[i][j] == '#') {
ok = false;
break;
}
}
if (ok) ans++;
}
cout << ans << '\n';
return 0;
}
T4:Only one of two
考虑二分答案
记 \(f(x)\) 表示在 \(1 \sim x\) 中满足条件的数的个数
那么 \(f(x) = \lfloor\frac{x}{n}\rfloor + \lfloor\frac{x}{m}\rfloor - 2 \times \frac{x}{\operatorname{lcm}(n, m)}\)
判定条件为 \(f(x) \geqslant k\)
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
ll n, m, k;
cin >> n >> m >> k;
ll l = lcm(n, m);
auto f = [&](ll x) {
ll c = x/n + x/m - x/l*2;
return c >= k;
};
ll wa = 0, ac = 1e18;
while (ac-wa > 1) {
ll wj = (ac+wa)/2;
if (f(wj)) ac = wj; else wa = wj;
}
cout << ac << '\n';
return 0;
}
T5:Alternating String
注意到操作 \(1\) 并不会更改区间 \([l, r],[1, l-1], [r+1, n]\) 中的相邻元素之间的关系,而只会影响 \(s_{l-1}\) 和 \(s_l\) 以及 \(s_r\) 和 \(s_{r+1}\) 的关系
可以用 std::set
来维护两个相同字符的关系,即若 \(s_i = s_{i+1}\),则将 \(i+1\) 加入 set
中,对于操作 \(2\),只需在 set
中查找是否存在大于等于 \(l+1\) 的某个元素不超过 \(r\) 即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, q;
cin >> n >> q;
string s;
cin >> s;
set<int> st;
rep(i, n-1) {
if (s[i] == s[i+1]) st.insert(i+1);
}
st.insert(n+1);
rep(qi, q) {
int type, l, r;
cin >> type >> l >> r;
--l;
if (type == 1) {
if (st.count(l)) st.erase(l); else st.insert(l);
if (st.count(r)) st.erase(r); else st.insert(r);
}
else {
int i = *st.lower_bound(l+1);
if (i < r) puts("No");
else puts("Yes");
}
}
return 0;
}
T6:Breakdown
先将所有点按 \(W_i\) 的大小做升序排序,然后跑一遍01背包即可
记 dp[v]
表示点 \(v\) 上有 \(1\) 个棋子时从这个点开始执行操作的最大次数
记 dp2[j]
表示 \(\sum W_i = j\) 时的 \(\sum dp[u]\) 的最大值
代码实现
#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 n, m;
cin >> n >> m;
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> w(n), a(n);
rep(i, n) cin >> w[i];
rep(i, n) cin >> a[i];
vector<int> vs(n);
rep(i, n) vs[i] = i;
sort(vs.begin(), vs.end(), [&](int i, int j) { return w[i] < w[j]; });
vector<int> dp(n);
for (int v : vs) {
vector<int> dp2(w[v]);
for (int u : to[v]) {
if (w[u] >= w[v]) continue;
for (int j = w[v]-1; j >= w[u]; --j) {
dp2[j] = max(dp2[j], dp2[j-w[u]]+dp[u]);
}
}
dp[v] = dp2[w[v]-1]+1;
}
ll ans = 0;
rep(i, n) ans += (ll)a[i]*dp[i];
cout << ans << '\n';
return 0;
}
T7:Highest Ratio
记 \(S_i = A_1 + A_2 + \cdots + A_i\)
倒序维护点 \((i, S_i)\) 构成的上凸包即可
时间复杂度为 \(\mathcal{O}(n)\)
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct P {
ll x, y;
P(ll x=0, ll y=0): x(x), y(y) {}
};
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<ll> s(n+1);
rep(i, n) s[i+1] = s[i]+a[i];
vector<double> ans(n);
vector<P> ps;
ps.emplace_back(n, s[n]);
for (int i = n-1; i >= 0; --i) {
P p(i, s[i]);
while (ps.size() >= 2) {
P a = ps[ps.size()-1];
P b = ps[ps.size()-2];
a.x -= p.x; a.y -= p.y;
b.x -= p.x; b.y -= p.y;
if (a.y*b.x > b.y*a.x) break;
ps.pop_back();
}
P a = ps.back();
a.x -= p.x; a.y -= p.y;
ans[i] = 1.*a.y/a.x;
ps.emplace_back(p);
}
rep(i, n) printf("%.10f\n", ans[i]);
return 0;
}