@xiaoziyao
2021-05-10T10:25:15.000000Z
字数 2226
阅读 990
解题报告
CF870F Paths解题报告:
个顶点的图,对于点对,如果那么之间有一条长度为的无向边,求图上点对两两之间距离之和。(如果无法到达则距离为)
好题。
下面令为质数集合。
首先不难发现不可能与其他结点连边,因此直接不管。
然后对于点对分情况讨论(设为的最小质因子,为作为最小质因子在的出现次数):
上述数组可以用一次线性筛处理出来,加上统计时间复杂度仍为。
#include<stdio.h>
#define int long long
const int maxn=10000005;
int n,pcnt,all,tot1,tot2,tot3,tot4;
int p[maxn],c[maxn],phi[maxn],cnt[maxn],minn[maxn],sum[maxn];
inline int max(int a,int b){
return a>b? a:b;
}
inline int calc(int l,int r){
return l>r? 0:sum[r]-sum[l-1];
}
signed main(){
scanf("%lld",&n);
c[1]=phi[1]=1;
for(int i=2;i<=n;i++){
if(c[i]==0)
p[++pcnt]=i,minn[i]=i,phi[i]=i-1;
for(int j=1;j<=pcnt;j++){
if(i*p[j]>n)
break;
c[i*p[j]]=1,minn[i*p[j]]=p[j];
if(i%p[j]==0){
phi[i*p[j]]=phi[i]*p[j];
break;
}
phi[i*p[j]]=phi[i]*(p[j]-1);
}
cnt[minn[i]]++;
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+cnt[i];
all=tot1=(n-1)*(n-2)/2;
for(int i=2;i<=n;i++)
tot1-=(phi[i]-1);
for(int i=1;i<=pcnt;i++){
tot3+=cnt[p[i]]*calc(max(n/p[i]+1,p[i]+1),n/2);
tot4+=cnt[p[i]]*calc(max(n/2+1,p[i]+1),n);
}
tot2=(n-1)*(n-2)/2-tot1-tot3-tot4;
printf("%lld\n",tot1*1+tot2*2+tot3*3+tot4*0);
return 0;
}