数论害人不浅啊(虽然这不是一道数论题)
题目描述
前置芝士
gcd
话说 共产党 真的好啊
好吧我还是给个链接就跑
一般来说,我们用的都是辗转相除法
MST
好吧我还是给个链接就跑
附:稀疏图(边数较少的图)或边有序的图一般用
K
r
u
s
k
a
l
Kruskal
Kruskal,否则用
P
r
i
m
Prim
Prim
贪心分析
这道题,相当于是一道 最大生成树 。(其实和最小生成树没啥两样,从大到小选边即可)
所以,按照
K
r
u
s
k
a
l
Kruskal
Kruskal的思想,先把边从大到小选出来就好了啊。
分析
怎么从大到小选边?
如果一个数是另一个数的倍数,那么这两个数的最大公约数就是另外那个数!所以连边尽量就要连有这样关系的边,对每一个数的倍数筛选一下就好。
至于从大到小,因为边权就是被枚举倍数的那个数,所以那个数从大到小枚举即可。
时间复杂度问题
这个就是找倍数,和埃氏筛法很相似,时间复杂度也是相同的,是
O
(
n
log
log
n
)
O(n\log\log n)
O(nloglogn),看得懂有兴趣的朋友可以看一下证明
代码
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<ctime>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cctype>
#include<string>
#include<sstream>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;
#define reg register
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int getc() { return p1 == p2 && (++p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; }
//#define getchar getc
template<typename T>
inline T read() {
T a = 0; char f = 1, c = getchar();
while(c < '0' || c > '9') {
if(c == -1) return -1;
if(c == '-') f = -f;
c = getchar();
}
while('0' <= c && c <= '9') {
a = (a << 3) + (a << 1) +(c ^ 48);
c = getchar();
}
return a;
}
template<class T>
inline int write(T x) {
if(x < 0) {
putchar('-');
x = (~x) + 1;
}
if(x / 10) write(x / 10);
return putchar(x % 10 | 48);
}
template<class T>
inline int write(T x, char c) {
return write(x) && putchar(c);
}
inline bool OpenFile() {
freopen("planet.in", "r", stdin);
freopen("planet.out", "w", stdout);
return 1;
}
//bool _Open = OpenFile();
const int MAXN = 200001;
int n = read<int>();
int fa[MAXN];
inline void makeSet(int n) { for(reg int i = 1; i <= n; i++) fa[i] = i; }
inline int findSet(int x) { while(x != fa[x]) x = fa[x] = fa[fa[x]]; return x; }
int x;
long long MST;
int main() {
makeSet(n);
for(reg int i = n; i >= 1; i--) {
for(reg int j = i * 2; j <= n; j += i) {
int fi = findSet(i), fj = findSet(j);
if(fi != fj) {
fa[fi] = fj;
x++;
MST += i;
if(x == n - 1) return !write(MST);
}
}
}
}