[cf809E]Surprise me

令$d=gcd(a_{i},a_{j})$,则$varphi(a_{i}a_{j})=frac{varphi(a_{i})varphi(a_{j})d}{varphi(d)}$(证明直接质因数分解即可)

枚举gcd并莫比乌斯反演,可得为$sum_{T=1}^{n}sum_{d|T}frac{dmu(frac{T}{d})}{varphi(d)}sum_{i=1}^{frac{n}{T}}sum_{j=1}^{frac{n}{T}}varphi(iT)varphi(jT)dis(p_{iT},p_{jT})$(其中$p_{i}$表示$i$所在的位置,即$p_{a_{i}}=i$)

对于$sum_{d|T}frac{dmu(frac{T}{d})}{varphi(d)}$,$o(nln n)$预处理即可,对于后半部分,先对所有$p_{iT}$并建出虚树,可以看作一棵$frac{n}{T}$个点的数,第$i$个点点权$v_{i}=varphi(iT)$,求$sum_{i=1}^{n'}sum_{j=1}^{n'}v_{i}v_{j}dis(i,j)$

将距离拆为两部分,即$dis(i,j)=dep_{i}+dep_{j}-2dep_{lca(i,j)}$,前半部分即$2(sum_{i=1}^{n'}v_{i})(sum_{i=1}^{n'}v_{i}dep_{i})$,后半部分考虑枚举lca,即统计其不同的两棵子树中点权乘积和

换言之,维护子树内点权和$sum_{k}$,那么即$sum_{son}(sum_{k}-sum_{son})sum_{son}$,再乘上$2dep_{k}$即可

时间复杂度为$o(nln nlog_{2}n)$(建虚树排序),可以通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 200005
  4 #define mod 1000000007
  5 struct ji{
  6     int nex,to;
  7 }edge[N<<1];
  8 vector<int>v;
  9 int E,n,x,y,ans,p[N],vis[N],mu[N],phi[N],f[N],head[N],a[N],dfn[N],sh[N],st[N],sum[N],fa[N][21];
 10 bool cmp(int x,int y){
 11     return dfn[x]<dfn[y];
 12 }
 13 int ksm(int n,int m){
 14     if (!m)return 1;
 15     int s=ksm(n,m>>1);
 16     s=1LL*s*s%mod;
 17     if (m&1)s=1LL*s*n%mod;
 18     return s;
 19 }
 20 void add(int x,int y){
 21     edge[E].nex=head[x];
 22     edge[E].to=y;
 23     head[x]=E++;
 24 }
 25 int lca(int x,int y){
 26     if (sh[x]<sh[y])swap(x,y);
 27     for(int i=20;i>=0;i--)
 28         if (sh[fa[x][i]]>=sh[y])x=fa[x][i];
 29     if (x==y)return x;
 30     for(int i=20;i>=0;i--)
 31         if (fa[x][i]!=fa[y][i]){
 32             x=fa[x][i];
 33             y=fa[y][i];
 34         }
 35     return fa[x][0];
 36 }
 37 void dfs1(int k,int f,int s){
 38     dfn[k]=++x;
 39     sh[k]=s;
 40     fa[k][0]=f;
 41     for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
 42     for(int i=head[k];i!=-1;i=edge[i].nex)
 43         if (edge[i].to!=f)dfs1(edge[i].to,k,s+1);
 44 }
 45 int dfs2(int k){
 46     int ans=0;
 47     for(int i=head[k];i!=-1;i=edge[i].nex){
 48         ans+=dfs2(edge[i].to);
 49         ans=(ans+2LL*sum[edge[i].to]*sum[k]%mod*sh[k])%mod;
 50         sum[k]=(sum[k]+sum[edge[i].to])%mod;
 51         sum[edge[i].to]=0;
 52     }
 53     head[k]=-1;
 54     return ans;
 55 }
 56 int calc(int k){
 57     int s=0,ans=0;
 58     v.clear();
 59     for(int i=k;i<=n;i+=k){
 60         v.push_back(a[i]);
 61         s=(s+phi[i])%mod;
 62     }
 63     sort(v.begin(),v.end(),cmp);
 64     E=st[0]=0;
 65     if (v[0]!=1)st[++st[0]]=1;
 66     for(int i=0;i<v.size();i++){
 67         x=lca(v[i],st[st[0]]);
 68         while ((st[0]>1)&&(sh[x]<=sh[st[st[0]-1]])){
 69             add(st[st[0]-1],st[st[0]]);
 70             st[0]--;
 71         }
 72         if ((st[0])&&(st[st[0]]!=x)){
 73             add(x,st[st[0]--]);
 74             st[++st[0]]=x;
 75         }
 76         st[++st[0]]=v[i];
 77     }
 78     while (st[0]>1){
 79         add(st[st[0]-1],st[st[0]]);
 80         st[0]--;
 81     }
 82     sum[1]=0;
 83     for(int i=k;i<=n;i+=k){
 84         sum[a[i]]=phi[i];
 85         ans=(ans+1LL*sh[a[i]]*phi[i]%mod*(s-phi[i]+mod))%mod;
 86     }
 87     return 2LL*(ans-dfs2(1)+mod)%mod;
 88 }
 89 int main(){
 90     mu[1]=phi[1]=1;
 91     for(int i=2;i<N-4;i++){
 92         if (!vis[i]){
 93             p[++p[0]]=i;
 94             mu[i]=-1;
 95             phi[i]=i-1;
 96         }
 97         for(int j=1;(j<=p[0])&&(i*p[j]<N-4);j++){
 98             vis[i*p[j]]=1;
 99             if (i%p[j]){
100                 mu[i*p[j]]=mu[i]*mu[p[j]];
101                 phi[i*p[j]]=phi[i]*phi[p[j]];
102             }
103             else{
104                 mu[i*p[j]]=0;
105                 phi[i*p[j]]=phi[i]*p[j];
106                 break;
107             }
108         }
109     }
110     for(int i=1;i<N-4;i++)
111         for(int j=i;j<N-4;j+=i)f[j]=(f[j]+1LL*i*mu[j/i]%mod*ksm(phi[i],mod-2))%mod;
112     scanf("%d",&n);
113     for(int i=1;i<=n;i++){
114         scanf("%d",&x);
115         a[x]=i;
116     }
117     memset(head,-1,sizeof(head));
118     for(int i=1;i<n;i++){
119         scanf("%d%d",&x,&y);
120         add(x,y);
121         add(y,x);
122     }
123     x=0;
124     dfs1(1,1,0);
125     memset(head,-1,sizeof(head));
126     for(int i=1;i<=n;i++)ans=(ans+1LL*f[i]*calc(i))%mod;
127     printf("%lld",1LL*ksm(n,mod-2)*ksm(n-1,mod-2)%mod*ans%mod);
128 } 
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/13915041.html