zoukankan      html  css  js  c++  java
  • Codeforces.871D.Paths(莫比乌斯反演 根号分治)

    题目链接


    (Description)

    给定(n),表示有一张(n)个点的无向图,两个点(x,y)之间有权值为(1)的边当且仅当(gcd(x,y) eq1)。求(1sim n)任意两点之间的最短路长度的和是多少。两个点不连通最短路长度为(0)
    (nleq10^7)

    (Solution)

    具体看这里吧,前面也挺重要的但我不抄了就简单记一下了(好像反而写的很详细了)
    先分类讨论一下,然后记(mn_x)(x)的最小质因子,主要的问题在于求:$$sum_{x,y}[gcd(x,y)=1][mn_x imes mn_yleq n]$$

    反演一下(当然下面这个式子求出来要除以(2)):$$egin{aligned}上式&=sum_{d=1}^nmu(d)sum_{dmid x}sum_{dmid y}[mn_x imes mn_yleq n]&=sum_{x=1}^nsum_{y=1}^n[mn_x imes mn_yleq n]+sum_{d=2}^nmu(d)sum_{d|x}sum_{d|y}[mn_x imes mn_yleq n]end{aligned}$$

    前面部分可以直接拿个桶然后前缀和一下。对于后面的部分,我们考虑:

    1. (dleqsqrt n)时,因为(dmid x),所以有(mn_xleq mn_d),即一定有(mn_x imes mn_yleq n)。那么合法方案数是(lfloorfrac nd floor^2)
    2. (d>sqrt n)时,设(x=k_1d,y=k_2d),那么有(k_1,k_2leqsqrt n)(k_1,k_2 eq1)时,(k_1 imes k_2leq n)显然合法。
      (k)有一个是(1)时,假设是(k_2)(mn_x imes mn_y)就是(k_1d=x),显然也是(leq n)
      (k_1=k_2=1)时,若(d)不是质数,那么(d)一定存在一个因子(leqsqrt n),那么也有(mn_x imes mn_y=mn_d^2leq n)
      所以当且仅当(k_1=k_2=1)(d)为质数时,((x,y))不合法。那么合法方案数就是(lfloorfrac nd floor^2)-1。

    那么枚举(d)就可以求出答案啦。


    //296ms	161300KB
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    typedef long long LL;
    const int N=1e7+5;
    
    int P[N>>3],phi[N],mu[N],mn[N],cnt[N];
    
    void Init(const int n)
    {
    	phi[1]=mu[1]=1;
    	for(int i=2,cnt=0; i<=n; ++i)
    	{
    		if(!mn[i]) P[++cnt]=mn[i]=i, phi[i]=i-1, mu[i]=-1;
    		for(int j=1,v; j<=cnt&&(v=i*P[j])<=n; ++j)
    		{
    			mn[v]=P[j];
    			if(i%P[j]) phi[v]=phi[i]*(P[j]-1), mu[v]=-mu[i];
    			else {phi[v]=phi[i]*P[j], mu[v]=0; break;}
    		}
    	}
    }
    
    int main()
    {
    	int n; scanf("%d",&n); Init(n);
    	LL ans=0,t2=0,t3=0,tot=0;
    	for(int i=2,half=n>>1; i<=n; ++i) if(mn[i]!=i||i<=half) ++tot, t2+=i-1-phi[i], ++cnt[mn[i]];
    	tot=tot*(tot-1)>>1;//总合法对数 
    	for(int i=2; i<=n; ++i) cnt[i]+=cnt[i-1];
    	for(int i=2,half=n>>1; i<=n; ++i) if(mn[i]!=i||i<=half) t3+=cnt[n/mn[i]];
    	for(int d=2,m=sqrt(n); d<=n; ++d)
    	{
    		LL tmp=1ll*(n/d)*(n/d);
    		if(d>m&&mn[d]==d) --tmp;
    		t3+=mu[d]*tmp;
    	}
    	t3>>=1, ans+=t2+(t3<<1)+(tot-t2-t3)*3;
    	printf("%I64d
    ",ans);
    
    	return 0;
    }
    
  • 相关阅读:
    2017.1.16【初中部 】普及组模拟赛C组总结
    用Redis实现分布式锁 与 实现任务队列
    Mysql+Keepalived双主热备高可用操作记录
    Linux下防御DDOS攻击的操作梳理
    真正的ddos防御之道,简单干脆有效!
    ip黑白名单防火墙frdev的原理与实现
    一种简单的处理大流量访问的方法
    PHP解决网站大流量与高并发
    PHP反射机制实现自动依赖注入
    nginx 根据域名和地址跳转
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10627403.html
Copyright © 2011-2022 走看看