luogu P8207 题解

Posted chifan-duck

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P8207 题解相关的知识,希望对你有一定的参考价值。

在暴力建边的情况下可以 kruskal 求生成树。

但是这样是 \\(O(n^2)\\) 的。

因为 \\(lcm(x,y) = x \\times y / \\gcd(x,y)\\)

所以 \\(\\gcd(x,y)\\) 越大我们的答案越优。

但是枚举 \\(x\\)\\(y\\)\\(\\gcd(x,y)\\) 也是会超时的。

但是我们用 正难则反 的思想,对于每一个 \\(i \\in[L,R]\\) 枚举倍数。

\\(i\\) 是这些数的最大公因数的因数。

而这样做是 \\(\\sum_i=1^i=n n/i = \\log n\\) 的。

因此总复杂度是 \\(O(n \\log^2 n)\\) 的。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn =4e6+100;
int tot;
struct node
    int u,v,w;
edge[maxn];
bool cmp(node a,node b)
    return a.w<b.w;

int fa[maxn];
int found(int u)
    if(fa[u]==u)
        return u;
    
    else
        return fa[u]=found(fa[u]);
    

int res=0;   hg
signed main()
    int l,r;
    cin>>l>>r;
    for(int i=l;i<=r;i++) fa[i]=i;
    for(int i=1;i<=r;i++)
        int v=ceil(l*1.0/i)*i;
        for(int j=ceil(l*1.0/i)*i;j<=r;j+=i)
            if(v!=j)
                edge[++tot].u=v;
                edge[tot].v=j;
                edge[tot].w=v*j/__gcd(v,j);
            
        
    
    sort(edge+1,edge+tot+1,cmp);
    for(int i=1;i<=tot;i++)
        int u=edge[i].u;
        int v=edge[i].v;
        int w=edge[i].w;
        if(found(u)!=found(v))
            //cout<<u<<\' \'<<v<<\' \'<<w<<\'\\n\';
            fa[found(u)]=found(v);
            res+=w;
        
    
    cout<<res;


以上是关于luogu P8207 题解的主要内容,如果未能解决你的问题,请参考以下文章

luogu P1343 地震逃生 题解

(luogu题解搬运系列)luogu p2651 添加括号Ⅲ

luogu P2245 星际导航 题解

luogu P1452 题解

luogu P1186 玛丽卡 题解

luogu题解 P3709 大爷的字符串题