zoukankan      html  css  js  c++  java
  • 【Codeforces 809 E】—Surprise me!(欧拉函数+莫比乌斯反演+虚树)

    传送门


    考虑有ϕ(ij)=ϕ(i)ϕ(j)gcd(i,j)ϕ(gcd(i,j))phi(ij)=phi(i)*phi(j)*frac{gcd(i,j)}{phi(gcd(i,j))}

    然后就可以枚举gcdgcd乱莫反了

    推出来最后就是
    ans=hT(h)i,jnhϕ(hi)ϕ(hj)dis(p[ih],p[jh])ans=sum_{h}T(h)sum_{i,j}^{frac n h}phi(hi)phi(hj)dis(p[ih],p[jh])
    p[i]p[i]表示权值为ii的点
    T(n)=dnμ(nd)dϕ(d)T(n)=sum_{d|n}frac{mu(frac n d)d}{phi(d)}
    然后随便虚树搞一下就完了
    复杂度O(nlog2n)O(nlog^2n)

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int mod=1e9+7;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Mul(int &a,int b){a=1ll*a*b%mod;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    cs int N=200005;
    int mu[N],phi[N],pr[N],T[N],tot;
    bitset<N> vis;
    int gcd(int a,int b){
    	return b?gcd(b,a%b):a;
    }
    inline void init(){
    	cs int len=N-5;
    	mu[1]=phi[1]=1;
    	for(int i=2;i<=len;i++){
    		if(!vis[i])pr[++tot]=i,phi[i]=i-1,mu[i]=mod-1;
    		for(int j=1;j<=tot&&i*pr[j]<=len;j++){
    			vis[i*pr[j]]=1;
    			if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;}
    			phi[i*pr[j]]=phi[i]*phi[pr[j]],mu[i*pr[j]]=mod-mu[i];
    		}
    	}
    	for(int i=1;i<=len;i++){
    		int iv=Inv(phi[i]);
    		for(int j=1;i*j<=len;j++)
    		Add(T[i*j],mul(mul(mu[j],i),iv));
    	}
    }
    int dep[N],fa[N],top[N],siz[N],son[N],in[N],out[N],dfn;
    vector<int> e[N];
    void dfs1(int u){
    	siz[u]=1;
    	for(int i=0;i<e[u].size();i++){
    		int v=e[u][i];
    		if(v==fa[u])continue;
    		fa[v]=u,dep[v]=dep[u]+1;
    		dfs1(v),siz[u]+=siz[v];
    		if(siz[v]>siz[son[u]])son[u]=v;
    	}
    }
    void dfs2(int u,int tp){
    	top[u]=tp,in[u]=++dfn;
    	if(son[u])dfs2(son[u],tp);
    	for(int i=0;i<e[u].size();i++){
    		int v=e[u][i];
    		if(v==fa[u]||v==son[u])continue;
    		dfs2(v,v);
    	}
    	out[u]=dfn;
    }
    inline int Lca(int u,int v){
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		u=fa[top[u]];
    	}
    	return dep[u]<dep[v]?u:v;
    }
    inline int dis(int u,int v){
    	return dep[u]+dep[v]-2*dep[Lca(u,v)];
    }
    int pos[N],a[N],n;;
    namespace XS{
    	vector<pii> e[N];
    	int p[N],s[N],sum,tot,ans;
    	int stk[N],top;
    	inline bool comp(int a,int b){
    		return in[a]<in[b];
    	}
    	inline void addedge(int u,int v){
    		int d=dis(u,v);
    		e[u].pb(pii(v,d));
    	}
    	void dfs(int u){
    		for(pii &x:e[u]){
    			int v=x.fi;
    			dfs(v);
    			Add(ans,mul(x.se,mul(dec(sum,s[v]),s[v])));
    			Add(s[u],s[v]);
    		}
    	}
    	void dfs2(int u){
    		for(pii &x:e[u])
    		dfs2(x.fi);
    		s[u]=0,e[u].clear();
    	}
    	inline int calc(int x){
    		top=tot=sum=ans=0;
    		for(int i=1;i*x<=n;i++)p[++tot]=pos[i*x],Add(sum,phi[i*x]),s[p[tot]]=phi[i*x];
    		sort(p+1,p+tot+1,comp);
    		stk[++top]=p[1];
    		for(int i=2;i<=tot;i++){
    			int lca=Lca(stk[top],p[i]);
    			while(in[lca]<in[stk[top]]){
    				if(in[lca]>=in[stk[top-1]]){
    					addedge(lca,stk[top--]);
    					if(stk[top]!=lca)stk[++top]=lca;
    					break;
    				}
    				addedge(stk[top-1],stk[top]),top--;
    			}
    			stk[++top]=p[i];
    		}
    		while(top>1)addedge(stk[top-1],stk[top]),top--;
    		dfs(stk[1]),dfs2(stk[1]);
    		return mul(ans,2);
    	}
    }
    int main(){
    	init();
    	n=read();
    	for(int i=1;i<=n;i++)a[i]=read(),pos[a[i]]=i;
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		e[u].pb(v),e[v].pb(u);
    	}
    	dfs1(1),dfs2(1,1);
    	int res=0;
    	for(int h=1;h<=n;h++){
    		Add(res,mul(T[h],XS::calc(h)));
    	}
    	cout<<mul(res,Inv(mul(n,n-1)));
    }
    
  • 相关阅读:
    setStyleSheet来设定窗口部件的样式
    Qt中设置widget背景颜色/图片的注意事项(使用样式表 setStyleSheet())
    Qt编程—去掉标题栏和设置窗口透明用法
    php设计模式总结
    典型的MVC架构图
    搜索引擎设计分析
    社区论坛设计分析
    (二) vim的Tabbar插件
    目录结构设计分析
    用户注册系统分析
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328408.html
Copyright © 2011-2022 走看看