zoukankan      html  css  js  c++  java
  • CF871D Paths

    link

    题意:

    n个点的无向图,若$gcd(x,y) eq1​$则$(x,y)​$有边,统计$1sim n​$构成的无向图两两点对最短路是之和是多少(两点不连通最短路记为0)?$nleq 10^7​$。

    题解:

    先分类讨论一下:

    1. 1和$>frac n2​$的素数是孤立点,排除掉,其余是一个联通块。
    2. $gcd(x,y) eq1longrightarrow dis(x,y)=1​$
    3. 记$mi[x]$为x的最小素因子,$mi[x] imes mi[y]leq nlongrightarrow dis(x,y)=2$
    4. 其余均可通过$x longrightarrow 2 imes mi[x] longrightarrow 2 imes mi[y] longrightarrow y$实现$dis(x,y)=3$

    分别考虑:

    1. 直接排除即可
    2. 方案数$=sum_x x-1-varphi(x)$
    3. 方案数$=sum_{x,y}[gcd(x,y)=1][mi[x] imes mi[y] leq n]$
    4. 剩余点对

    考虑第3种情况怎么求:

    看到$gcd​$想反演”:
    $$
    egin{aligned}
    ans&=sum_{d=1}^nmu(d)sum_{d|x}sum_{d|y}[mi[x] imes mi[y]leq n]\
    &=sum_{x=1}^nsum_{y=1}^n[mi[x] imes mi[y]leq n]+sum_{d=2}^nmu(d)sum_{d|x}sum_{d|y}[mi[x] imes mi[y]leq n]
    end{aligned}
    $$
    前一部分比较容易求解,直接开桶维护前缀和即可;

    后一部分再分类讨论:

    1. $dleq sqrt{n}​$:由于$d|x​$,所以必定有$mi[x]leq mi[d]​$,所以对于任意$d|x,d|y​$都有$mi[x] imes mi[y]leq n​$,所以可行方案数为$(frac n2)^2​$。
    2. $d>sqrt{n}$:由于$d|x,d|y$,若设$x=k_1d,y=k_2d$,那么有$k_1,k_2leq sqrt{n}$,故只有当$k_1=k_2=1$且d为质数时$mi[x] imes mi[y]>n$,可行方案数为$(frac n2)^2-1$。

    那么就只要枚举d就可以$mathcal{O}(1)$算答案了。

    使用线性筛求积性函数$varphi(i)$和$mu(i)​$。至此本题解决。

    复杂度$mathcal{O}(n)$。

    code:

     1 #include<bits/stdc++.h>
     2 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
     3 #define ll long long
     4 
     5 using namespace std;
     6 
     7 const int N=1e7+10;
     8 int n,cnt,phi[N],mu[N],p[N/10],vis[N],T[N],pre[N];
     9 ll sum1,sum2,sum3,ans,all;
    10 
    11 void sieve(int n){
    12     phi[1]=mu[1]=1;
    13     rep (i,2,n){
    14         if (!vis[i]) p[++cnt]=vis[i]=i,phi[i]=i-1,mu[i]=-1;
    15         for (int j=1;j<=cnt&&i*p[j]<=n;j++){
    16             vis[i*p[j]]=p[j];
    17             if (i%p[j]==0){phi[i*p[j]]=phi[i]*p[j]; break;}
    18             phi[i*p[j]]=phi[i]*(p[j]-1);
    19             mu[i*p[j]]=-mu[i];
    20         }
    21     }
    22 }
    23 
    24 int main(){
    25     scanf("%d",&n); sieve(n);
    26     rep (i,2,n) if (vis[i]!=i||i<=n/2) all++; all=all*(all-1)/2; //所有非0数对
    27     rep (i,2,n) sum1+=i-1-phi[i]; ans+=sum1;
    28     rep (i,2,n) if (vis[i]!=i||i<=n/2) T[vis[i]]++;
    29     rep (i,2,n) pre[i]=pre[i-1]+T[i];
    30     rep (i,2,n) if (vis[i]!=i||i<=n/2) sum2+=pre[n/vis[i]]; //不考虑gcd(x,y)=1的条件
    31     int m=sqrt(n);
    32     rep (i,2,n){ //减去gcd(x,y)>1的对数:枚举i为>1的gcd
    33         ll tmp=0;
    34         tmp+=(ll)(n/i)*(n/i); //vis[ki]<=vis[i]故两个vis[ki]相乘必定<=n
    35         if (i>m&&vis[i]==i) tmp--; //vis[ki]<=vis[k],而k<=m,故只有当k1=k2=1且i为质数时vis[k1i]*vis[k2i]>n
    36         sum2+=mu[i]*tmp;
    37     }
    38     sum2/=2; ans+=sum2*2;
    39     ans+=(all-sum1-sum2)*3;
    40     printf("%lld
    ",ans); 
    41     return 0;
    42 }
    View Code
  • 相关阅读:
    第二节:Android APP自动化测试之环境配置以及脚本设计(课工场)
    第一节:Appium介绍(课工场)
    Dockerfile 相关命令
    Nginx 原理及与 Apache 对比
    Windows 环境配置 Nginx
    Linux 命令大全(十九)——性能优化及常见问题
    Linux 命令大全(十八)——压缩打包
    Linux 命令大全(十七)——VI/VIM编辑器
    Linux 命令大全(十六)——计划任务
    Linux 命令大全(十五)——配置文件
  • 原文地址:https://www.cnblogs.com/bestFy/p/10423989.html
Copyright © 2011-2022 走看看