voidsolve() { int n, k; cin >> n >> k; if (n == 1) { cout << 0 << endl; return; } if (n <= k) { cout << 1 << endl; return; }
int arr[N]; arr[0] = n; int ans = 0; int pnt = 0; while (pnt < n-1) { int temp = arr[pnt]; int i = 0; for (; i < temp-1 && i < k-1; i++, pnt++) { arr[pnt] = 1; } arr[pnt] = temp - k+1; ans++; } cout<<ans<<endl; return; }
数学
用ceil上取整
1 2 3 4 5 6 7 8 9
voidsolve() { int n, k; cin >> n >> k; int ans = ceil((double)(n-1)/(k-1));
cout << ans << endl; return; }
用分式上取整
1 2 3 4 5 6 7 8 9
voidsolve() { int n, k; cin >> n >> k; int ans = (n - 1 + k - 2) / (k - 1);
std::vector<i64> a(n); for (int i = 0; i < n; i++) { std::cin >> a[i]; }
std::vector<std::vector<int>> adj(n); for (int i = 1; i < n; i++) { int u, v; std::cin >> u >> v; u--; v--; adj[u].push_back(v); adj[v].push_back(u); }
std::vector<i64> f(n, inf), g(n, inf); std::vector<int> r(n); auto dfs = [&](auto self, int x, int p) -> void { int d = 0; for (auto y : adj[x]) { if (y == p) { continue; } d++; self(self, y, x); }
std::vector<i64> val(d + 2); i64 sum = 0; for (auto y : adj[x]) { if (y == p) { continue; } sum += f[y]; if (r[y] < d + 2) { val[r[y]] += g[y] - f[y]; } } for (int i = 0; i < d + 2; i++) { i64 res = sum + val[i] + (i + 1) * a[x]; if (res < f[x]) { g[x] = f[x]; f[x] = res; r[x] = i; } elseif (res < g[x]) { g[x] = res; } } }; dfs(dfs, 0, -1);
std::vector<std::vector<int>> adj(n); for (int i = 1; i < n; i++) { int u, v; std::cin >> u >> v; u--; v--; adj[u].push_back(v); adj[v].push_back(u); }
注意是二维数组
dfs lambda写法来遍历树,x是当前,p是父节点 用y==p防止死循环。
val存的某个子节点隔一个后的和。 d是子节点数量。 f[x]最小值。 g[x]次优解 res=:
sum 表示如果不击杀当前节点 x,其所有子树的最小健康值减少量。
val[i] 表示如果我们选择击杀 i + 1 个子节点(包括当前节点),那么这些子节点的额外贡献。
(i + 1) * a[x] 表示在这一轮选择击杀 i + 1 个子节点时,这些节点对健康值减少的贡献。
将这三部分加在一起,我们得到了在当前轮次选择击杀 i + 1 个子节点时的总健康值减少量。这个总减少量是我们需要最小化的目标,因此我们通过遍历所有可能的 i 值来找到最小的 res。
constint N = 3e5 + 10; constint INF = 0x3f3f3f3f3f3f3f3f;
structedges { int to; int before; } e[N * 2];
int cnt, last[N]; int p[N];
voidadd(int u, int v) { e[++cnt].to = v; e[cnt].before = last[u]; last[u] = cnt; } constint K = 25; int f[N][K + 1];
voiddfs_f(int u, int fa) { for (int i = 1; i <= K; i++) f[u][i] = p[u] * i; for (int i = last[u]; i; i = e[i].before) { int v = e[i].to; if (v == fa) continue; dfs_f(v, u); for (int j = 1; j <= K; j++) { int res = INF; for (int k = 1; k <= K; k++) if (k != j) res = min(res, f[v][k]); f[u][j] += res; } } }
voidinit(int n) { cnt = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= K; j++) f[i][j] = 0; last[i] = 0; } }
voidsolve() { int n; cin >> n; init(n); int sum = 0; for (int i = 1; i <= n; i++) { cin >> p[i]; sum += p[i]; } int de[n + 1] = {}; for (int i = 1, u, v; i <= n - 1; i++) { cin >> u >> v; add(u, v); add(v, u); } dfs_f(1, 0); int ans = INF; for (int i = 1; i <= K; i++) ans = min(ans, f[1][i]); cout << ans << "\n"; }
signedmain() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while (t--) { solve(); } }