#include<bits/stdc++.h> using LL = longlong; usingnamespace std;
int T = 1;
voidsolve() { int n, s1, e1; bool ok = true; cin >> n >> s1 >> e1; for (int i = 1; i < n; i++) { int s, e; cin >> s >> e; if (s >= s1 && e >= e1) ok = false; } cout << (ok ? s1 : -1) << '\n'; }
voidsolve() { LL ans = 0, ways = 1; string s; cin >> s; int n = s.size(); for (int i = 0; i < n; i++) { int j = i; while (j + 1 < n && s[j + 1] == s[j]) j++; int len = j - i + 1; ans += len - 1; ways = ways * len % MOD; i = j; } for (int i = 1; i <= ans; i++) ways = ways * i % MOD; cout << ans << ' ' << ways << '\n'; }
双指针算法复习
求连续区间长度
1 2 3 4 5 6 7 8 9
for (int i = 0; i < n; i++) { int j = i; while (j + 1 < n && s[j + 1] == s[j]) j++; int len = j - i + 1; // ... i = j; }
求最长连续不重复子区间长度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
voidsolve() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; int ans = 0; for (int i = 0, j = 0; i < n; i++) { s[a[i]] ++; while (s[a[i]] > 1) s[a[j++]] --; ans = min(ans, i - j + 1); } cout << ans << '\n'; }
#include<iostream> #include<cstring> #include<vector> usingnamespace std; using LL = longlong; template <constint T> structModInt { conststaticint mod = T; int x; ModInt(int x = 0) : x(x % mod) {} ModInt(longlong x) : x(int(x % mod)) {} intval(){ return x; } ModInt operator+(const ModInt &a) const { int x0 = x + a.x; returnModInt(x0 < mod ? x0 : x0 - mod); } ModInt operator-(const ModInt &a) const { int x0 = x - a.x; returnModInt(x0 < 0 ? x0 + mod : x0); } ModInt operator*(const ModInt &a) const { returnModInt(1LL * x * a.x % mod); } ModInt operator/(const ModInt &a) const { return *this * a.inv(); } booloperator==(const ModInt &a) const { return x == a.x; }; booloperator!=(const ModInt &a) const { return x != a.x; }; voidoperator+=(const ModInt &a) { x += a.x; if (x >= mod) x -= mod; } voidoperator-=(const ModInt &a) { x -= a.x; if (x < 0) x += mod; } voidoperator*=(const ModInt &a) { x = 1LL * x * a.x % mod; } voidoperator/=(const ModInt &a) { *this = *this / a; } friend ModInt operator+(int y, const ModInt &a) { int x0 = y + a.x; returnModInt(x0 < mod ? x0 : x0 - mod); } friend ModInt operator-(int y, const ModInt &a) { int x0 = y - a.x; returnModInt(x0 < 0 ? x0 + mod : x0); } friend ModInt operator*(int y, const ModInt &a) { returnModInt(1LL * y * a.x % mod); } friend ModInt operator/(int y, const ModInt &a) { returnModInt(y) / a; } friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x; } friend istream &operator>>(istream &is, ModInt &t) { return is >> t.x; }
ModInt pow(int64_t n)const { ModInt res(1), mul(x); while (n) { if (n & 1) res *= mul; mul *= mul; n >>= 1; } return res; }
ModInt inv()const { int a = x, b = mod, u = 1, v = 0; while (b) { int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if (u < 0) u += mod; return u; } }; using mint = ModInt<998244353>;
intmain() {
cin.tie(0); cout.tie(0); ios::sync_with_stdio(0);
int n; cin >> n; vector<int> s(n + 1); for (int i = 1; i <= n; i++) cin >> s[i], s[i] ^= s[i - 1]; mint ans = 0; for (int i = 0; i <= 30; i++) { mint cnt[2] = {1, 0}, sum[2] = {0}; for (int j = 1; j <= n; j++) { int bit = (s[j] >> i & 1); ans += (j * cnt[bit ^ 1] - sum[bit ^ 1]) * (1 << i); cnt[bit] += 1; sum[bit] += j; } } cout << ans << '\n'; }
voidsolve() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; int f[2][35]; for (int i = 0; i < n; i++) for (int j = 0; j < 30; j++) f[(a[i] << j) & 1][j] ++;
LL ans = 0; for (int i = 0; i < n; i++) for (int j = 0; j < 30; j++) ans += f[((a[i] << j) & 1) ^ 1][j] * (1 << j); cout << ans << '\n'; }
Codeforces Round 899 (Div. 2)
A. Increasing Sequence
题意: 给定序列 a, 定义序列 b
如果满足各个数大于 0 且单调递增, 同时 \(a_i\neq b_i\), 则称 b
为好数组. 找到所有好数组中 \(b_n\)
的最小值.
voidsolve() { int n; cin >> n; LL Or = 0; vector<LL> a(n + 1); int ans = 0; for (int i = 0; i < n; i++) { int k; cin >> k; while (k--) { int x; cin >> x; a[i] |= 1LL << x; } Or |= a[i]; } for (int i = 1; i <= 50; i++) { if (Or >> i & 1) { LL v = 0; for (int j = 0; j < n; j++) if (~a[j] >> i & 1) v |= a[j]; ans = max(ans, __builtin_popcountll(v)); } } cout << ans << '\n'; }
题解: x 的下界 \(\sum_{1}^{k}\),
上界 \(\sum_{n-k+1}^{n}\),
判断是否在这之间即可.
1 2 3 4 5 6 7 8 9 10
voidsolve() { int n, k; LL x; cin >> n >> k >> x; if (x >= 1LL * (1 + k) * k / 2 && x <= 1LL * (2 * n - k + 1) * k / 2) cout << "YES\n"; else cout << "NO\n"; }
D. Reverse Madness
题意: 给定小写字符组成的字符串 s, 长度为 n,
两个长度为 k 的整数数组 l 和 r,
两个数组满足
voidsolve() { LL a, b, n; cin >> a >> b >> n; vector<LL> x(n + 1); LL ans = 0; for (int i = 0; i < n; i++) { cin >> x[i]; ans += min(a - 1, x[i]); } cout << ans + b << endl; }
B. Jellyfish and Game
题意: 进行 k 轮比赛, A 有 \(n\) 个价值 \(a_i\) 的苹果, B 有 \(m\) 个价值 \(b_i\) 的苹果, 他们会进行 \(k\) 轮次的比赛, 如果 \(i\) 是奇数, A 可以交换 B
的一个苹果或者不动, 偶数就是轮到 B 行动.
A 和 B 都想最大化他们的分数, 求 A 最后最高分是多少.
题解: 每个选手的策略都是交换自己价值最低的苹果和对手价值最高的苹果,
或者考虑不进行交换(因为自己价值最低的比对手价值最高的还要高). 答案和
k 的奇偶相关, k 为奇数对 A 最优, 偶数则对 B 最优.
voidsolve() { int n, m, k; cin >> n >> m >> k; vector<LL> a(n), b(m); LL ans = 0; for (int i = 0; i < n; i++) cin >> a[i], ans += a[i]; for (int i = 0; i < m; i++) cin >> b[i];
voidsolve() { int n, m; LL ans = 0; cin >> n >> m;
int div = __gcd(n, m); n /= div, m /= div;
if (n % m == 0) cout << 0 << '\n'; elseif (__builtin_popcount(m) != 1) cout << -1 << '\n'; else { int t = __builtin_ffs(m) - 1; n %= m; // printf("n=%d m=%d t=%d\n", n, m, t); for (int i = 0; i < t; i++) { if (n >> i & 1) ans += (m - (1 << i)); } cout << 1ll * div * ans << '\n'; } }
D. Jellyfish and Mex
题意: 给定长度为 n 的非负整数数组 a,
m 初始化为 0, 然后执行 n 次如下的操作: 删去
a[i], 然后 m += MEX(a). 这里
MEX(a) 表示不属于数组 a 最小的数(minimum
excluded). 求 m 最小值.
voidsolve() { int n, p, q; cin >> n >> p >> q; for (int i = 0; i < p; i++) { int u, v; cin >> u >> v; isEnemy[u][v] = isEnemy[v][u] = 1; } for (int i = 0; i < q; i++) { int u, v; cin >> u >> v; isFriend[u][v] = isFriend[v][u] = 1; } LL ans = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; i < n; i++) { if (isFriend[i][j]) ans ++; elseif (!isEnemy[i][j]) { bool flag = true; for (int w = 0; w < n; w++) { if ((isFriend[w][j] && isEnemy[w][i]) || (isFriend[w][i] && isEnemy[w][j])) { flag = false; break; } } if (flag) ans ++; } } } cout << ans << '\n'; }
voidsolve() { int n, p, q; cin >> n >> p >> q; for (int i = 0; i < p; i++) { int u, v; cin >> u >> v; isFriend[u][v] = isFriend[v][u] = 1; } vector<PII> enemy; LL ans = 1ll * n * (n - 1) / 2; for (int i = 0; i < q; i++) { int u, v; cin >> u >> v; isEnemy[u][v] = isEnemy[v][u] = 1; ans --; enemy.push_back({u, v}); } for (int i = 0; i < q; i++) { int u = enemy[i].first, v = enemy[i].second; for (int w = 0; w < n; w++) { if (isFriend[u][w] && !isFriend[v][w] && !isEnemy[v][w]) { ans --; isEnemy[v][w] = isEnemy[w][v] = 1; } swap(u, v); if (isFriend[u][w] && !isFriend[v][w] && !isEnemy[v][w]) { ans--; isEnemy[v][w] = isEnemy[w][v] = 1; } } } cout << ans << '\n'; }
voidsolve() { int n, p; cin >> n >> p; vector<PII> c(n); for (int i = 0; i < n; i++) cin >> c[i].second; for (int i = 0; i < n; i++) cin >> c[i].first; c.push_back({p, n - 1}); LL ans = p; int tot = n - 1; sort(c.begin(), c.end()); for (int i = 0; tot && i < n + 1; i++) { if (c[i].second >= tot) { ans += 1ll * c[i].first * tot; break; } else { ans += 1ll * c[i].first * c[i].second; tot -= c[i].second; } } cout << ans << '\n'; }
voidsolve() { int n, m, k, a[2]; cin >> n >> m >> k; for (int i = 0; i <= m; i++) { st.insert(i); a[0] = i; for (int j = n; j >= 1; j--) { a[1] = a[0] % j; st.insert(a[1]); a[0] = a[1]; } if (st.size() == k) cout << "a[n + 1] = " << i << ", size is " << st.size() << " k is: " << k << '\n'; st.clear(); } }
voidsolve() { int n, m, k; cin >> n >> m >> k; int ans = 0; switch (k) { case1: ans = 1; break; case2: if (m > n) ans = n - 1 + m / n; else ans = m; break; case3: if (m > n) ans = m - n - (m / n) + 1; break; default: break; } cout << ans << '\n'; }
voidsolve() { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) for (int j = 2 * i; j <= n; j += i) a[i] = max(a[i], a[j]); sort(a + 1, a + n + 1); mint ans = 0, now = 1; for (int i = 1; i <= n; i++) { ans += now * a[i]; now *= 2; } cout << ans << '\n'; }
Educational
Codeforces Round 156 (Rated for Div. 2)
voidsolve() { int n; cin >> n; for (int x = 1; x <= 10; x++) { for (int y = x + 1; y <= 10; y++) { int z = n - x - y; if (x % 3 && y % 3 && z % 3 && z > 0 && z != x && z != y) { cout << "YES\n"; cout << x << ' ' << y << ' ' << z << '\n'; return; } } } cout << "NO\n"; }
mint ans = 1; string s; cin >> s; for (int i = 1; i <= n - 1; i++) if (s[i] == '?') ans *= i; cout << ((s[0] == '?') ? 0 : ans) << '\n'; while (m--) { int x; char c; cin >> x >> c; x--; mint p = x; if (x && s[x] == '?') ans *= p.inv(); s[x] = c; if (x && c == '?') ans *= x; cout << ((s[0] == '?') ? 0 : ans) << '\n'; } }
voidsolve() { int n, m; cin >> n >> m; int ans = -1; string x, s; cin >> x >> s; for (int i = 0; i <= 5; i++) { if (x.find(s) != x.npos) { ans = i; break; } x += x; } cout << ans << '\n'; }
voidsolve() { int a[3]; cin >> a[0] >> a[1] >> a[2]; int p = min({a[0], a[1], a[2]}); int ans = 0; bool ok = true; for (int i = 0; i < 3; i++) { ans += a[i] / p - 1; if (a[i] % p || ans > 3) ok = false; } cout << (ok ? "YES\n" : "NO\n"); }
voidsolve() { int n; cin >> n; int ma = 0; for (int i = 1; i <= n; i++) { cin >> a[i]; ma = max(ma, a[i]); st[a[i]] ++; } int ans = 0; while (st[ans]) ans ++; for (int i = 1; i <= n; i++) { if (!a[i]) ans = max({ans, a[i - 1], a[i + 1]}); } if (!ma) ans = 0; cout << ans << '\n'; }
voidsolve() { int n; cin >> n; n %= M; int ans = 20; if (n == 0) { cout << 0 << '\n'; return; } for (int i = 0; i <= 20; i++, n++) { int p = __builtin_ctz(n); ans = min(ans, 20 - p + i); } cout << ans << '\n'; }
voidsolve() { int n, m; cin >> n >> m; LL ans = -1; if (n >= 7) { int p = (1 << m) % 4; if (m >= 2) p += 4; ans = qpow(n % 10 * 6 % 10, p, 10); } cout << ans << '\n'; }
voidsolve() { int x, k; cin >> x >> k; for (int i = x; ; i++) { int y = i; int sum = 0; while (y) { sum += y % 10; y /= 10; } if (sum % k == 0) { cout << i << '\n'; break; } } }
LL ans = 0; int l = n; for (int i = 1; i <= n; i++) { if (ans != -1) { if (l > n - i && s[n - i] == '0') l --; else { // swap 1 with 0, find 0 on the left while (l > 0 && s[l - 1] != '0') l --; // no solution if (l == 0) ans = -1; else ans += n - i + 1 - l; l --; } } cout << ans << " \n"[i == n]; } }
C. Medium Design
题意: 一个初始大小 m 的数组 a, 初始化全为 0, 给出 n 组子区间 \([l_i, r_i]\),
你可以选择将子区间上的每一个元素自增 1. 最后, 计算 \(\max (a) - \min(a)\) 的最大值.
voidsolve() { int n, m; cin >> n >> m; vector<int> l(n), r(n); vector<PII> f; for (int i = 0; i < n; i++) { cin >> l[i] >> r[i]; l[i] --; if (l[i] != 0) { f.emplace_back(l[i], 1); f.emplace_back(r[i], -1); } } int ans = 0; int cur = 0, lst = 0; sort(f.begin(), f.end()); for (auto [x, y] : f) { if (x > lst) ans = max(ans, cur); cur += y; lst = x; } if (m > lst) ans = max(ans, cur); f.clear(); for (int i = 0; i < n; i++) { if (r[i] != m) { f.emplace_back(l[i], 1); f.emplace_back(r[i], -1); } } cur = 0, lst = 0; sort(f.begin(), f.end()); for (auto [x, y] : f) { if (x > lst) ans = max(ans, cur); cur += y; lst = x; } if (m > lst) ans = max(ans, cur); cout << ans << '\n'; }
子问题的处理其实也挺难度的.
D. Counting Rhyme
题意: 给定整数序列 \(a_1, a_2, \dots,
a_n\), 我们称 \((i,j)\) good
如果不存在 \(1\leqslant k\leqslant n\)
使得 \(a_i\) 和 \(a_j\) 都不能同时整除 \(a_k\). 其中 \(1\leqslant i < j \leqslant n\). 找出
good pair 的数量.
DP, 组合问题
Codeforces Round 905 (Div. 3)
A. Morning
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
voidsolve() { string s; cin >> s; LL ans = 0; char cur = '1'; for (int i = 0; i < 4; i++) { if (s[i] == '0') s[i] += 10; ans += abs(s[i] - cur) + 1; cur = s[i]; } cout << ans << '\n'; }
voidsolve() { int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; for (int m = 0; (1 << m) < n; m++) { int l = (1 << m) + 1; int r = min(n, 1 << (m + 1)); if (!is_sorted(a + l, a + r + 1)) { cout << "NO\n"; return; } } cout << "YES\n"; }
B. Deja Vu
题意: 给定数组 a 和 q 个询问 \(x_i\), 每次询问对 a 中能够整除 \(2^{x_i}\) 的元素加上 \(2^{x_i-1}\), 输出 q 次询问后的数组 a.
voidsolve() { int n, q; cin >> n >> q; set<int> mp; vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < q; i++) { int x; cin >> x; if (!mp.empty() && x >= *mp.begin()) continue; mp.insert(x); } for (int i = 0; i < n; i++) { int p = __builtin_ctz(a[i]); for (auto it = mp.begin(); it != upper_bound(mp.begin(), mp.end(), p); it++) a[i] += (1 << (*it - 1)); } for (int i = 0; i < n; i++) cout << a[i] << " \n"[i == n - 1]; }
voidsolve() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; sort(a, a + n); LL x = 0, ans = 0; int l = 0, r = n - 1; while (l < r) { if (x + a[l] < a[r]) { ans += a[l]; x += a[l]; a[l ++] = 0; } else { a[l] -= a[r] - x; ans += a[r] - x + 1; x = 0; a[r --] = 0; // x + a[l] == a[r] if (!a[l]) l ++; } } if (l == r && a[l]) { int tot = a[l] + x; if (a[l] == 1) ans ++; else { if (tot & 1) ans += tot / 2 - x + 2; else ans += tot / 2 - x + 1; } } cout << ans << '\n'; }
#include<bits/stdc++.h> using LL = longlong; using DLL = __int128_t; usingnamespace std;
constint MOD = 1e9 + 7, N = 1e5 + 5; int T = 1;
template <constint T> structModInt { conststaticint mod = T; int x; ModInt(int x = 0) : x(x % mod) {} ModInt(longlong x) : x(int(x % mod)) {} intval(){ return x; } ModInt operator+(const ModInt &a) const { int x0 = x + a.x; returnModInt(x0 < mod ? x0 : x0 - mod); } ModInt operator-(const ModInt &a) const { int x0 = x - a.x; returnModInt(x0 < 0 ? x0 + mod : x0); } ModInt operator*(const ModInt &a) const { returnModInt(1LL * x * a.x % mod); } ModInt operator/(const ModInt &a) const { return *this * a.inv(); } booloperator==(const ModInt &a) const { return x == a.x; }; booloperator!=(const ModInt &a) const { return x != a.x; }; voidoperator+=(const ModInt &a) { x += a.x; if (x >= mod) x -= mod; } voidoperator-=(const ModInt &a) { x -= a.x; if (x < 0) x += mod; } voidoperator*=(const ModInt &a) { x = 1LL * x * a.x % mod; } voidoperator/=(const ModInt &a) { *this = *this / a; } friend ModInt operator+(int y, const ModInt &a) { int x0 = y + a.x; returnModInt(x0 < mod ? x0 : x0 - mod); } friend ModInt operator-(int y, const ModInt &a) { int x0 = y - a.x; returnModInt(x0 < 0 ? x0 + mod : x0); } friend ModInt operator*(int y, const ModInt &a) { returnModInt(1LL * y * a.x % mod); } friend ModInt operator/(int y, const ModInt &a) { returnModInt(y) / a; } friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x; } friend istream &operator>>(istream &is, ModInt &t) { return is >> t.x; }
ModInt pow(int64_t n)const { ModInt res(1), mul(x); while (n) { if (n & 1) res *= mul; mul *= mul; n >>= 1; } return res; }
ModInt inv()const { int a = x, b = mod, u = 1, v = 0; while (b) { int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if (u < 0) u += mod; return u; } }; using mint = ModInt<MOD>;
// ans[base][x]: sum of log(k, base) from 1 to x map<LL, mint> ans[70]; int base;
// Example: // base = 3 // x = 40 // 1~2 3~8 9~26 27~40 // 0 1 2 3
mint get(LL x) { if (ans[base].contains(x)) return ans[base][x]; mint sum = 0; LL pow = 1; for (int i = 1; i <= 60; i++) { if (DLL(pow) * base > x) break; pow *= base;
LL l = pow, r = min(DLL(pow) * base - 1, DLL(x)); sum += i * mint(r - l + 1); } return ans[base][x] = sum; }
mint calc(LL x) { mint sum = 0; for (int i = 2; i <= 60; i++) { // 2^i and 2^{i+1} - 1 LL l = (1LL << i), r = (1LL << (i + 1)) - 1; if (l > x) break; // x > l: // i = [log(x, 2)] = f(x) r = min(r, x); base = i; sum += get(r); sum -= get(l - 1); } // Example: // x = 15 // i = 2 // sum = g(4) + ... + g(7) // i = 3 // sum = g(4)+ ... + g(8) + ... + g(15) return sum; }
Educational
Codeforces Round 157 (Rated for Div. 2)
A. Treasure Chest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
voidsolve() { int x, y, k; cin >> x >> y >> k; int ans = 0; if (y <= x) ans = x; else { ans = y; if (x + k < y) ans += y - (x + k); } cout << ans << '\n'; }
intdist(Point a, Point b) { returnabs(a.x - b.x) + abs(a.y - b.y); }
voidsolve() { int n; cin >> n; for (int i = 0; i < 2 * n; i++) cin >> a[i]; sort(a, a + 2 * n); int ans = 0; for (int i = 0; i < n; i++) p[i].x = a[i], p[i].y = a[2 * n - 1 - i];
for (int i = 1; i < n; i++) ans += dist(p[i], p[i - 1]); cout << ans << '\n';
for (int i = 0; i < n; i++) cout << p[i].x << ' ' << p[i].y << '\n'; }
voiddfs(int in, int out) { if (in == out && ans == m) { for (auto op : seq) cout << op << ' '; cout << '\n'; return; } if (in != n.size()) { in ++; t += n[in - 1]; seq.push_back('i'); dfs(in, out); in --; seq.pop_back(); t.pop_back(); } if (!t.empty()) { char ch = t.back(); if (ch == m[out]) { t.pop_back(); ans += ch; seq.push_back('o'); dfs(in, out + 1); t += ch; seq.pop_back(); ans.pop_back(); } } }
G. Safecracker
题意: 求满足下列方程的解
\[v - w^2 + x^3 - y^4 + z^5 =
target\]
target 是给定的一个数. 每个数会偏移一个 A, 答案就是
vwxyz 偏移后得到的一个字符序列, 如果有多组解,
输出字典序最大的一组解.
voidsolve() { int n, k; cin >> n >> k; string s; cin >> s;
int r = 0; for (int i = 0; i < n; i++) { while (r > 0 && ans[r - 1] < s[i] && n - i + r > n - k) r --; ans[r] = s[i]; r ++; } for (int i = 0; i < n - k; i++) cout << ans[i]; cout << '\n'; }
创新程序学设计-动态规划(周
3 班,第 12 周)
最爱的 DP 专题
A. Bone Collector
HDU 2602
题解: 0/1 背包的模板题
状态表示 f[i][j] 前 i 件物品选取体积不大于
j 的最大价值
怎么转移: 从 i-1 件开始:
选: f[i-1][j-v[i]]+w[i]
不选: f[i-1][j]
滚动数组优化: 因为转移只和上一层有关, DP 数组可以开到一维.
枚举 j 时需要倒序遍历: 保证每次更新状态的时候,
用的是上一轮的结果, 否则会把第 i
件物品重复放入背包(完全背包问题)
时间复杂度 \(O(NM)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
voidsolve() { memset(f, 0, sizeof f); int n, m; cin >> n >> m; for (int i = 0; i < n; i++) cin >> c[i]; for (int i = 0; i < n; i++) cin >> v[i];
for (int i = 0; i < n; i++) for (int j = m; j >= v[i]; j--) f[j] = max(f[j], f[j - v[i]] + c[i]);
cout << f[m] << '\n'; }
C. Common Subsequence
HDU 1159
题解: LCS, 求最长公共子序列 板子题
我们假设两个字符串分别为 a, b, 定义状态: f[i][j] 为 a 前
i 个字符和 b 前 j 个字符构成的 LCS 长度
voidsolve() { string a, b; while (cin >> a >> b) { memset(f, 0, sizeof f); int n = a.size(), m = b.size();
for (int i = 1; i <= n; i++) { int t = 0; for (int j = 1; j <= m; j++) { int now = f[j]; if (a[i - 1] == b[j - 1]) f[j] = t + 1; else f[j] = max(f[j], f[j - 1]); t = now; } } cout << f[m] << '\n'; } }
“海康威视杯“
2022年第十四届四川省大学生程序设计大赛
队伍 VP 了一下, 过了 B F H K, H 本来我首开的, 思路对了但忘开 LL
千古罪人. 哎, 下次一定会注意
K. Kooky Clock
一开始因为 PI 的精度卡了 2 发. 现在我会用 acos(-1.0)
了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
constdouble PI = acos(-1.0); voidsolve() { int T; cin >> T; for (int i = 0; i < 3; i++) cin >> l[i]; for (int i = 0; i < 3; i++) cin >> t[i]; double x = 0, y = 0; for (int i = 0; i < 3; i++) { double theta = (2.5 - (double)T * 2 / t[i]) * PI; x += cos(theta) * l[i]; y += sin(theta) * l[i]; } cout << fixed << setprecision(10) << x << ' ' << y << '\n'; }
H Hacking Interview Solution
题面很长, 但核心是在询问一个数组是否重复出现
一开始手写 Hash 但忘了双哈希怎么写, 然后想起可以 map 套 vector
小心 overflow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
voidsolve() { map<vector<int>, int> mp; cin >> n >> m; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < m; i++) { vector<int> t(n); for (int j = 0; j < n; j++) cin >> t[i]; mp[t] += 1; } LL ans = 0; for (auto [val, cnt] : mp) ans += 1LL * cnt * (cnt - 1) / 2; cout << ans << '\n'; }
voidsolve() { int n; cin >> n; int a = *lower_bound(primes, primes + cnt, 1 + n); int b = *lower_bound(primes, primes + cnt, a + n); int c = *lower_bound(primes, primes + cnt, b + n); cout << 1LL * a * b * min(1LL * a * a, (LL)c) << '\n'; }
Codeforces Round 946 (Div. 3)
好久没做题了, 练练
A. Phone Desktop
1 2 3 4 5 6 7 8 9
voidsolve(){ int x, y; cin >> x >> y; int ans = (y + 1) / 2; int l = x + y * 4 - ans * 15; if (l > 0) ans += (l + 14) / 15; cout << ans << '\n'; }
voidsolve() { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; i++) cin >> a[i]; map<TII, int> mp1, mp2, mp3, mp; LL ans = 0; for (int i = 0; i < n - 2; i++) { TII t = {a[i], a[i + 1], a[i + 2]}; mp[t]++; TII t1 = {0, a[i + 1], a[i + 2]}; mp1[t1]++; TII t2 = {a[i], 0, a[i + 2]}; mp2[t2]++; TII t3 = {a[i], a[i + 1], 0}; mp3[t3]++; ans += mp1[t1] - 1; ans += mp2[t2] - 1; ans += mp3[t3] - 1; ans -= 3 * (mp[t] - 1); } cout << ans << '\n'; }
D. Ingenuity-2
Codeforces Round 950 (Div. 3)
A. Problem Generator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
voidsolve() { vector<int> cnt(7); int n, m; cin >> n >> m; string s; cin >> s; for (int i = 0; i < n; i++) { cnt[s[i] - 'A'] ++; } int ans = 0; for (int i = 0; i < 7; i++) { ans += max(m - cnt[i], 0); } cout << ans << '\n'; }
B. Choosing Cubes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
voidsolve() { int n, f, k; cin >> n >> f >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } int m = a[f - 1]; sort(a.begin(), a.end(), greater<int>()); auto l = lower_bound(a.begin(), a.end(), m, greater<int>()) - a.begin(); auto r = upper_bound(a.begin(), a.end(), m, greater<int>()) - a.begin(); if (r <= k) cout << "YES\n"; elseif (l >= k) cout << "NO\n"; else cout << "MAYBE\n"; }
注: 不排序也可以统计大于等于 a[f-1] 的个数, 然后和
k 比较
C. Sofia and the Lost
Operations
题解: d 的最后一次操作可以覆盖掉之前的操作, 所以需要保证
d[m-1] 在 b 中. 然后只需考虑 a 和 b
序列之间的差异, 这些差异应当都包含在 d 中即可.
voidsolve() { int n, m; cin >> n; vector<int> a(n), b(n); for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n; i++) cin >> b[i]; cin >> m; vector<int> d(m); for (int i = 0; i < m; i++) cin >> d[i]; bool flag = true; if (find(b.begin(), b.end(), d[m - 1]) == b.end()) { flag = false; } multiset<int> p(d.begin(), d.end()); for (int i = 0; i < n; i++) { if (a[i] != b[i]) { if (p.find(b[i]) == p.end()) flag = false; p.extract(b[i]); } } if (flag) { cout << "YES\n"; } else { cout << "NO\n"; } }
voidsolve() { int n; cin >> n; set<int> st; for (int i = 0; i < n; i++) { int x; cin >> x; st.insert(x); } if (st.size() == 1) { cout << "NO\n"; } else { cout << "YES\n"; for (int i = 0; i < n; i++) { cout << (i == 1 ? 'R' : 'B'); } cout << '\n'; } }
B. Large Addition
猜结论: 首位必须为 1, 最后一位不为 9, 中间位不为 0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
voidsolve() { string x; cin >> x; int n = x.size(); int ans = 1; if (x[0] != '1') ans = 0; for (int i = 1; i < n - 1; i++) { if (x[i] == '0') ans = 0; } if (x[n - 1] == '9') ans = 0; if (ans) cout << "YES\n"; else cout << "NO\n"; }
C1. Magnitude (Easy Version)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
voidsolve() { int n; cin >> n; LL mx = 0, mn = 0; for (int i = 0; i < n; i++) { int x; cin >> x; mn += x; mx += x; mx = max(mx, abs(mn)); } cout << mx << '\n'; }