CF809E Surprise me!

CF809E Surprise me!

题面:Luogu

解析

题意即求:

\[\frac{1}{n(n-1)}\sum_{i=1}^{n}\sum_{j=1}^{n}\varphi(a_{i}a_{j})dist(i,j) \]

其中,\(a_{i}\)\(n\)的一个排列。

首先有:\(\varphi(ij)=\frac{d\varphi(i)\varphi(j)}{\varphi(d)}\),其中\(d=gcd(i,j)\),证明带入公式即可。

那么有:

\[\sum_{i=1}^{n}\sum_{j=1}^{n}\varphi(a_{i}a_{j})dist(i,j) \]

\[=\sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(a_{i},a_{j})=d]\varphi(a_{i})\varphi(a_{j})dist(i,j) \]

考虑莫比乌斯反演,设:

\[g(d)=\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(a_{i},a_{j})=d]\varphi(a_{i})\varphi(a_{j})dist(i,j) \]

\[f(d)=\sum_{i=1}^{n}\sum_{j=1}^{n}[d|gcd(a_{i},a_{j})]\varphi(a_{i})\varphi(a_{j})dist(i,j) \]

那么有:

\[=\sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{d|k}\mu(\frac{k}{d})f(k) \]

求出\(f(k)\)后枚举倍数贡献即可\(O(nlogn)\)统计答案,考虑如何计算\(f(k)\)

观察到只有\(a_{i}\)\(k\)的倍数才有贡献,那我们把\(k\)的倍数的点提出来建虚树。

现在就是求:

\[\sum_{i=1}^{t}\sum_{j=1}^{t}\varphi(a_{i})\varphi(a_{j})dist(i,j) \]

\[=\sum_{i=1}^{t}\varphi(a_{i})dep[i]\sum_{j=1}^{t}\varphi(a_{j})+\sum_{i=1}^{t}\varphi(a_{i})\sum_{j=1}^{t}\varphi(a_{j})dep[j]-2*\sum_{i=1}^{t}\sum_{j=1}^{t}\varphi(a_{i})\varphi(a_{j})d[lca] \]

前面两部分可以\(O(n)\)统计,后面一部分可以枚举\(lca\),组合一下子树,也可以\(O(n)\)统计。

那么总复杂度即为\(O(nlogn)\),解决了这个问题。

代码


#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;

inline int In(){
    char c=getchar();
    int x=0,ft=1;
    for(;c<'0'||c>'9';c=getchar()){
        if(c=='-'){
            ft=-1;
        }
    }
    for(;c>='0'&&c<='9';c=getchar()){
        x=x*10+c-'0';
    }
    return x*ft;
}

const int P=1e9+7,N=2e5+5;

inline void Add(int& x,int y){
    x+=y;
    if(x>=P){
        x-=P;
    }
}

inline int Mul(int x,int y){
    return 1ll*x*y%P;
}

int n,a[N],pos[N],inv[N];
int h[N],e_tot=0;
struct Edge{
    int to,nex;
    Edge(){}
    Edge(int to,int nex):to(to),nex(nex){}
}e[N<<1];

inline void add(int u,int v){
    e[++e_tot]=Edge(v,h[u]);
    h[u]=e_tot;
}

int d[N],fa[N],sz[N],son[N];

void dfs1(int u,int pre){
    d[u]=d[pre]+1;
    fa[u]=pre;
    sz[u]=1;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to;
        if(v==fa[u]){
            continue;
        }
        dfs1(v,u);
        sz[u]+=sz[v];
        if(!son[u]||sz[v]>sz[son[u]]){
            son[u]=v;
        }
    }
}

int top[N],dfn[N],low[N],dfc=0;

void dfs2(int u,int pre){
    top[u]=pre;
    dfn[u]=++dfc;
    if(son[u]){
        dfs2(son[u],pre);
    }
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to;
        if(v==fa[u]||v==son[u]){
            continue;
        }
        dfs2(v,v);
    }
    low[u]=dfc;
}

inline int LCA(int x,int y){
    while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]]){
            swap(x,y);
        }
        x=fa[top[x]];
    }
    return d[x]<d[y]?x:y;
}

int p[N],pc,mu[N],phi[N];
bool vis[N];

void Sieve(int n){
    mu[1]=phi[1]=1;
    for(int i=2;i<=n;++i){
        if(!vis[i]){
            p[++pc]=i;
            mu[i]=-1;
            phi[i]=i-1;
        }
        for(int j=1;j<=pc;++j){
            if(1ll*i*p[j]>n){
                break;
            }
            vis[i*p[j]]=1;
            if(i%p[j]){
                mu[i*p[j]]=-mu[i];
                phi[i*p[j]]=phi[i]*(p[j]-1);
            }
            else{
                mu[i*p[j]]=0;
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }
        }
    }
}

int t[N<<1],tc,stk[N];
vector<int> E[N];

inline bool cmp(int a,int b){
    return dfn[a]<dfn[b];
}

inline void add_edge(int u,int v){
    E[u].push_back(v);
}

int ans,sum1,sum2,sum3,sum[N],f[N],g[N];
bool fg[N];

void dfs(int u){
    if(fg[u]){
        Add(sum1,phi[a[u]]);
        Add(sum2,Mul(phi[a[u]],d[u]));
        sum[u]=phi[a[u]];
        Add(sum3,Mul(d[u],Mul(phi[a[u]],phi[a[u]])));
    }
    for(int i=0,v;i<E[u].size();++i){
        v=E[u][i];
        dfs(v);
        Add(sum3,Mul(d[u],Mul(2,Mul(sum[u],sum[v]))));
        Add(sum[u],sum[v]);
    }
}

void del(int u){
    sum[u]=fg[u]=0;
    for(int i=0,v;i<E[u].size();++i){
        v=E[u][i];
        del(v);
    }
    E[u].clear();
}

int main(){
    n=In();
    for(int i=1;i<=n;++i){
        a[i]=In();
        pos[a[i]]=i;
    }
    for(int i=1,u,v;i<n;++i){
        u=In();
        v=In();
        add(u,v);
        add(v,u);
    }
    dfs1(1,0);
    dfs2(1,1);
    Sieve(n);
    inv[0]=inv[1]=1;
    for(int i=2;i<=n;++i){
        inv[i]=Mul(P-P/i,inv[P%i]);
    }
    for(int d=1;d<=n;++d){
        tc=0;
        for(int i=d;i<=n;i+=d){
            t[++tc]=pos[i];
            fg[pos[i]]=1;
        }
        sort(t+1,t+1+tc,cmp);
        for(int i=tc;i>1;--i){  
            t[++tc]=LCA(t[i-1],t[i]);
        }
        sort(t+1,t+1+tc,cmp);
        tc=unique(t+1,t+1+tc)-t-1;
        stk[1]=t[1];
        for(int i=2,stp=1;i<=tc;++i){
            while(stp&&low[stk[stp]]<dfn[t[i]]){
                --stp;
            }
            add_edge(stk[stp],t[i]);
            stk[++stp]=t[i];
        }
        sum1=sum2=sum3=0;
        dfs(t[1]);
        Add(f[d],Mul(2,Mul(sum1,sum2)));
        Add(f[d],P-Mul(2,sum3));
        del(t[1]);
    }
    for(int d=1;d<=n;++d){
        for(int i=d;i<=n;i+=d){
            Add(g[d],Mul(f[i],(mu[i/d]+P)%P));
        }
    }
    for(int d=1;d<=n;++d){
        Add(ans,Mul(Mul(d,inv[phi[d]]),g[d]));
    }
    printf("%d\n",Mul(Mul(inv[n-1],inv[n]),ans));
    return 0;
}

posted @ 2019-09-06 16:20  pkh68  阅读(169)  评论(0编辑  收藏  举报