2 条题解
-
0
积少成多
本题可以采取二分答案的策略,主要步骤如下:
- 假定拥有 x 的力量可以完成该任务。
- 任取一点(以左端点为例),从该点开始dfs搜索。如果所需力量小于等于 x, 那么打上标记。
- 如果所有点都被打上标记,那么x就是可行
- 二分搜索 x 找到最优解。
复杂度为, 其中是端点,是模数,是点的取值范围(此处为).
本题也有其它解法,比如并查集等。
#include <bits/stdc++.h> using namespace std; int power(int a, int k, int p) // a^k%p { int res = 1 % p; while (k) { if (k & 1) res = (long long)res * a % p; a = (long long)a * a % p; k >>= 1; } return res; } int get_weight(int x, int y, int k) { return (power(x, y, k) + power(y, x, k)) % k; } struct edge { int u, v, w; edge(int u, int v, int k) : u(u), v(v), w(get_weight(u, v, k)) {} bool operator<(const edge& o) const { return w < o.w; } bool operator>(const edge& o) const { return w > o.w; } }; void solve() { int l, r, k; cin >> l >> r >> k; vector<int> p(r - l + 1); iota(p.begin(), p.end(), 0); function<int(int)> find = [&](int x) -> int { if (p[x] == x) return x; return p[x] = find(p[x]); }; priority_queue<edge, vector<edge>, greater<edge>> heap; for (int i = l; i < r; i++) { heap.push(edge(i, i + 1, k)); if ((i << 1) > r) continue; heap.push(edge(i, i << 1, k)); } int cnt = 0, ans = 0; while (heap.size()) { auto [u, v, w] = heap.top(); heap.pop(); int pu = find(u - l), pv = find(v - l); if (pu == pv) continue; cnt++; p[pu] = pv; ans = w; // cout << u << " -> " << v << " : " << w << "\n"; if (cnt == r - 1) break; } cout << ans << "\n"; } int main() { // int T = 1; cin >> T; while (T--) solve(); return 0; }
- 1
信息
- ID
- 180
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 66
- 已通过
- 15
- 上传者