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个因子,说明该数能写成为a2∗b2a^2*b^2a2∗b2的形式或者a8a^8a8的形式。这里ab都为质数。
因此我们先做出2000000以内的质数表,然后前者暴力或者求前缀和都可以,后者直接暴力。做的时候小心越界。因此我很不要脸的用了python。
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import 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.stdin
n = int(fp.readline())
N = 2000001
b = [0] * N
prime = []
sz = 0
for i in range(2, N):
if b[i] == 0:
prime.append(i)
sz += 1
for j in range(sz):
if i * prime[j] >= N:
break
b[i * prime[j]] = 1
if i % prime[j] == 0:
break
ans = 0
for i in range(sz):
for j in range(i + 1, sz):
if (prime[i] ** 2) * (prime[j] ** 2) > n:
break
ans += 1
for i in range(sz):
t = prime[i] ** 8
if t > n:
break
ans += 1
print(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使用闵可夫斯基和优化。
563

被折叠的 条评论
为什么被折叠?



