THUPC2022初赛 A.最小公倍树 解题报告

THUPC2022 A.最小公倍树

给定一个点编号在 $[L,R]$ 范围内的完全图,边 $(u,v)$ 的权值为 $\mathrm{lcm}(u, v)$,请你求出这张图的最小生成树权值和。

$L,R \leq 10^6,R - L \leq 10^5$

解题思路:

Kruskal 优化建图。

观察到如果直接建图的时间复杂度是 $\mathcal{O}((R-L)^2 )$ 的,无法接受。但是发现在这个过程中,有很多边实际上是可以省略的,接下来来发掘一下这些边的性质。

首先我们有
$$
\mathrm{lcm}(u, v) = \frac{u\times v}{\mathrm{gcd}(u,v)}
$$
这实际上启发了我们从 $\mathrm{gcd}(u,v)$ 的角度进行思考,我们发现,如果将两个有共同因子的点连边,这条边的权值是较小的。观察到 $L,R \leq 10^6$,这启发我们去枚举这个因子。同时我们发现,如果对于一个因子 $x$ 来说,在 $[L,R]$ 里的数都满足 $kx,(k+1)x\dots (k+p)x$ 这样的形式,显然对于 $(k+1)x$ 及后面的数,向 $kx$ 连边是最优秀的,这样我们对于一个因子最多建边数量为 $\lfloor\frac{R-L}{x}\rfloor$ 的。

而我们可以枚举因子,因子的范围是 $[2,R]$ ,最后我们建边的数量就应该是 $\lfloor\frac{R-L}{2}\rfloor + \lfloor\frac{R-L}{3}\rfloor + \dots + \lfloor\frac{R-L}{R}\rfloor$ 根据调和级数,这个东西的边数是 $\mathcal{O}((R-L) \log R)$ 的,实际上这个上界很松,具体数据会更小,极限数据大概是 $10^5$ 左右的,建出边后跑 Kruskal 就过了。

时间复杂度 $\mathcal{O}(((R-L) \log R) \log ((R-L) \log R))$ 。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const int N = 1e6 + 10;

int l,r,f[N],buc[N];
bool vis[N];

ll gcd(ll a,ll b) {
return !b ? a : gcd(b,a%b);
}

ll lcm(ll a,ll b) {
return a / gcd(a,b) * b;
}

int find(int x) {return f[x] == x ? x : f[x] = find(f[x]);}

struct node {
int l,r;
ll w;
friend inline bool operator < (const node &a,const node &b) {
return a.w < b.w;
}
};

vector <node> edge;

void Kruskal() {
sort(edge.begin(),edge.end());
int cnt = 0;
ll ans = 0;
for (auto e : edge) {
int x = e.l,y = e.r;ll w = e.w;
if (find(x) != find(y)) {
//printf("%d %d %lld\n",x,y,w);
f[max(find(x),find(y))] = min(find(x),find(y));
ans += w;
}
}
printf("%lld\n",ans);
}

signed main() {
read(l,r);
ll ans = 0;
for (int i = l;i <= r;++i) f[i] = i,buc[i] = 1;
for (int i = 2;i <= r;++i) {
//if (vis[i]) continue;
int cnt = 0,fis = 0;

for (int j = i;j <= r;j += i) {
if (buc[j] && !fis) fis = j;
if (buc[j]) edge.push_back((node){fis,j,lcm(fis,j)});
vis[j] = 1;
}

if (i >= l) edge.push_back((node){fis,l,lcm(fis,l)});
}
Kruskal();
return 0;
}

作者

Doubeecat

发布于

2022-03-12

更新于

2025-09-18

许可协议