@xiaoziyao
2021-05-10T02:25:15.000000Z
字数 2226
阅读 1406
解题报告
CF870F Paths解题报告:
个顶点的图,对于点对,如果那么之间有一条长度为的无向边,求图上点对两两之间距离之和。(如果无法到达则距离为)
好题。
下面令为质数集合。
首先不难发现不可能与其他结点连边,因此直接不管。
然后对于点对分情况讨论(设为的最小质因子,为作为最小质因子在的出现次数):
上述数组可以用一次线性筛处理出来,加上统计时间复杂度仍为。
#include<stdio.h>#define int long longconst 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;}
