C
BFS。放入所有的H点,bfs在D步内能访问到的点。
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;int h, w, d;
string s[1100];
int a[1100][1100];
queue<pii> qu;int dirs[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};int main(){//freopen("in.txt", "r", stdin);cin >> h >> w >> d;for (int i = 0; i < h; ++i) {cin >> s[i];}memset(a, 0x3f, sizeof(a));for (int i = 0; i < h; ++i) {for (int j = 0; j < w; ++j) {if (s[i][j] == 'H') {a[i][j] = 0;qu.push({ i, j });}}}while (qu.size()) {auto [r, c] = qu.front();int step = a[r][c];if (step == d) {break;}qu.pop();for (auto [dr, dc] : dirs) {int nr = dr + r, nc = dc + c;if (nr >= 0 && nr < h && nc >= 0 && nc < w && s[nr][nc] == '.') {if (a[nr][nc] > step + 1) {qu.push({ nr, nc });a[nr][nc] = step + 1;}}}}int ans = 0;for (int i = 0; i < h; ++i) {for (int j = 0; j < w; ++j) {if (a[i][j] <= d) ans++;}}printf("%d\n", ans);return 0;
}
D
简单数论题。
有9个因子,说明该数能写成为 a 2 ∗ b 2 a^2*b^2 a2∗b2的形式或者 a 8 a^8 a8的形式。这里ab都为质数。
因此我们先做出2000000以内的质数表,然后前者暴力或者求前缀和都可以,后者直接暴力。做的时候小心越界。因此我很不要脸的用了python。
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharmimport bisect
import copy
import sys
from itertools import permutations
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)def main():items = sys.version.split()fp = open("in.txt") if items[0] == "3.10.6" else sys.stdinn = int(fp.readline())N = 2000001b = [0] * Nprime = []sz = 0for i in range(2, N):if b[i] == 0:prime.append(i)sz += 1for j in range(sz):if i * prime[j] >= N:breakb[i * prime[j]] = 1if i % prime[j] == 0:breakans = 0for i in range(sz):for j in range(i + 1, sz):if (prime[i] ** 2) * (prime[j] ** 2) > n:breakans += 1for i in range(sz):t = prime[i] ** 8if t > n:breakans += 1print(ans)if __name__ == "__main__":main()
E
这种N的排列求最佳匹配已经没有什么算法复杂度可言,关键是找到一种方法去贪心。
考虑类似kruscal求最小生成树的做法,对边排序,从小到大加入。实际上,当点对在同一颗最小生成子树中时,点对的f值就是最小生成树当前遍历的边w。
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;int n, m, k;
struct Edge {ll w;int u, v;
} e[200020];int fa[200020];
int dep[200020];
int cnta[200020], cntb[200020];int get(int u) {return u == fa[u] ? u : fa[u] = get(fa[u]);
}int merge(int u, int v) {int fu = get(u), fv = get(v);if (fu == fv) return fu;if (dep[fu] < dep[fv]) swap(fu, fv);cnta[fu] += cnta[fv];cntb[fu] += cntb[fv];fa[fv] = fu;if (dep[fu] == dep[fv]) dep[fu] ++;return fu;
}int main(){//freopen("in.txt", "r", stdin);cin >> n >> m >> k;for (int i = 0; i < m; ++i) {int u, v;ll w;cin >> u >> v >> w;e[i] = { w, u, v };}for (int i = 0; i < k; ++i) {int u;cin >> u;cnta[u] ++;}for (int i = 0; i < k; ++i) {int u;cin >> u;cntb[u] ++;}sort(e, e + m, [&](Edge x, Edge y) {return x.w < y.w;});for (int i = 1; i <= n; ++i) {fa[i] = i, dep[i] = 0;}ll ans = 0;for (int i = 0; i < m; ++i) {auto [w, u, v] = e[i];int f = merge(u, v);int mn = min(cnta[f], cntb[f]);ll t = w * mn;cnta[f] -= mn, cntb[f] -= mn;ans += t;}printf("%lld\n", ans);return 0;
}
F
分组背包,将同一个颜色归为一组,然后对每一组开一个背包计算在这一组上面容量为j时能获得的最大分数。
设 g ( i , j ) g(i,j) g(i,j)是第i组运行完后容量为j时的最大分数。
当前背包的容量为p,分数为u
f ( i , j ) = min ( g ( i − 1 , j − p ) + u + k , f ( i , j − p ) + u ) f(i,j)=\min(g(i-1,j-p) + u + k,f(i,j-p)+u) f(i,j)=min(g(i−1,j−p)+u+k,f(i,j−p)+u)
最后再将f更新到g
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;ll f[50001], nx[50001];
const ll INF = 1ll << 60;
int n, x;
ll k;
vector<pii> a[505];int main(){//freopen("in.txt", "r", stdin);cin >> n >> x >> k;for (int i = 1; i <= n; ++i) {int p, u, c;cin >> p >> u >> c;a[c].push_back({ p, u });}for (int i = 1; i <= x; ++i) f[i] = -INF;for (int i = 1; i <= n; ++i) {for (int j = 0; j <= x; ++j)nx[j] = -INF;for (auto [p, u] : a[i]) {for (int j = x; j >= p; --j) {ll temp = -INF;if (f[j - p] >= 0) {temp = max(temp, f[j - p] + u + k);}if (nx[j - p] >= 0) {temp = max(temp, nx[j - p] + u);}nx[j] = max(nx[j], temp);}}for (int j = 0; j <= x; ++j) {f[j] = max(f[j], nx[j]);}}ll ans = 0;for (int i = 0; i <= x; ++i) {ans = max(ans, f[i]);}printf("%lld\n", ans);return 0;
}
G
这一期的G题有点难度,dp使用闵可夫斯基和优化。