T1:3.14
模拟
代码实现
s = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679'
n = int(input())
ans = s[0:n+2]
print(ans)
T2:Roulette
模拟
代码实现
#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> c(n);
vector<vector<int>> a(n);
rep(i, n) {
cin >> c[i];
a[i] = vector<int>(c[i]);
rep(j, c[i]) cin >> a[i][j];
}
int x;
cin >> x;
vector<bool> bet(n);
rep(i, n) {
bet[i] = any_of(a[i].begin(), a[i].end(), [&](int e) { return e == x;});
}
int cmin = 37;
rep(i, n) {
if (bet[i]) cmin = min(cmin, c[i]);
}
vector<int> ans;
rep(i, n) {
if (bet[i] and c[i] == cmin) ans.push_back(i+1);
}
cout << ans.size() << '\n';
for (int i : ans) cout << i << ' ';
return 0;
}
T3:Rotate Colored Subsequence
模拟
可以预处理一下每种颜色的位置
代码实现
#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;
string s;
cin >> s;
vector<int> c(n);
rep(i, n) cin >> c[i];
vector<vector<int>> ps(m);
rep(i, n) ps[c[i]-1].push_back(i);
string ans = s;
rep(i, m) {
int l = ps[i].size();
rep(j, l) {
ans[ps[i][(j+1)%l]] = s[ps[i][j]];
}
}
cout << ans << '\n';
return 0;
}
T4:LOWER
显然只有最后一个大小写颠倒的操作有效,那么我们只需找到这个时刻,按顺序在此时刻之前的操作 \(1\),然后在此时刻做大小写颠倒操作,在此操作之后继续执行操作 \(1\)
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, q;
string s;
cin >> n >> s >> q;
vector<int> lt(n);
int last = -1, type = 2;
rep(qi, q) {
int t, x; char c;
cin >> t >> x >> c;
--x;
if (t == 1) {
s[x] = c;
lt[x] = qi;
}
else {
last = qi;
type = t;
}
}
rep(i, n) {
if (lt[i] < last) {
if (type == 2) s[i] = tolower(s[i]);
else s[i] = toupper(s[i]);
}
}
cout << s << '\n';
return 0;
}
T5:Roulettes
期望dp
记 dp[x]
表示剩余 \(x\) 点的状态的期望
初始值:\(\operatorname{dp}[0] = 0\)
答案为 \(\operatorname{dp}[M]\)
注意需要特判 \(S_{ij} = 0\) 时的情况
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
inline void chmin(double& a, double b) { if (a > b) a = b; }
int main() {
int n, m;
cin >> n >> m;
vector<int> c(n), p(n);
vector<vector<int>> a(n);
rep(i, n) {
cin >> c[i] >> p[i];
a[i] = vector<int>(p[i]);
rep(j, p[i]) cin >> a[i][j];
}
const double INF = 1e18;
vector<double> dp(m+1, INF);
dp[0] = 0;
for (int r = 1; r <= m; ++r) {
rep(i, n) {
double now = 0;
double b = 0;
for (int d : a[i]) {
if (d) now += dp[max(0, r-d)];
else b += 1;
}
now /= p[i]; b /= p[i];
now += c[i]; now /= 1-b;
chmin(dp[r], now);
}
}
printf("%.10f\n", dp[m]);
return 0;
}
T6:A Certain Game
在合并过程树上自顶向下做树形dp即可,可以用并查集来做合并
代码实现
#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 mint = modint998244353;
int main() {
int n;
cin >> n;
vector<vector<int>> to(n);
vector<int> sz(n*2-1, 1);
vector<int> gv(n);
rep(i, n) gv[i] = i;
dsu uf(n);
rep(i, n-1) {
int p, q;
cin >> p >> q;
--p; --q;
p = uf.leader(p);
q = uf.leader(q);
int v = to.size();
to.push_back({gv[p], gv[q]});
uf.merge(p, q);
gv[uf.leader(p)] = v;
sz[v] = uf.size(p);
}
int root = to.size()-1;
vector<mint> dp(to.size());
auto dfs = [&](auto f, int v) -> void {
for (int u : to[v]) {
dp[u] = dp[v] + mint(sz[u])/sz[v];
f(f, u);
}
};
dfs(dfs, root);
rep(i, n) cout << dp[i].val() << ' ';
return 0;
}
T7:Amulets
我们不去考虑有 \(i\) 个护身符时能打倒几只怪兽,而是考虑为了打倒 \(i\) 只怪兽需要几个护身符。
这样一来,原问题就变成了处理对序列进行 “插入一个数” “删除一个数”以及 “求至少选多少个数才能使总和 \(\geqslant X\)” 的询问的问题!
这个问题可以用一个 std::multiset
维护所有 \(\geqslant X\) 的数,以及另一个 std::multiset
维护剩下的数来解决!
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct S {
ll h;
multiset<ll> s, t;
S(int h): h(h) {}
void fix() {
while (h <= 0) {
h += *s.rbegin();
t.insert(*s.rbegin());
s.erase(prev(s.end()));
}
while (t.size() and h > *t.begin()) {
h -= *t.begin();
s.insert(*t.begin());
t.erase(t.begin());
}
}
void add(ll x) {
if (t.size() and *t.begin() < x) t.insert(x);
else h -= x, s.insert(x);
fix();
}
void del(ll x) {
if (t.find(x) != t.end()) {
t.erase(t.find(x));
}
else {
h += x;
s.erase(s.find(x));
fix();
}
}
int get() { return t.size(); }
};
int main() {
int n, m, h;
cin >> n >> m >> h;
vector<int> a(n), b(n);
rep(i, n) cin >> a[i] >> b[i], b[i]--;
vector<ll> sum(m);
S s(h);
rep(i, m) s.add(0);
vector<int> ans(m+1);
rep(i, n) {
s.del(sum[b[i]]);
sum[b[i]] += a[i];
s.add(sum[b[i]]);
ans[s.get()] = i+1;
}
rep(i, m) ans[i+1] = max(ans[i+1], ans[i]);
rep(i, m+1) cout << ans[i] << ' ';
return 0;
}