[关闭]
@xiaoziyao 2021-05-10T02:25:15.000000Z 字数 2226 阅读 810

CF870F Paths解题报告

解题报告


CF870F Paths解题报告:

更好的阅读体验

Codeforces Round 870考试总结

题意

个顶点的图,对于点对,如果那么之间有一条长度为的无向边,求图上点对两两之间距离之和。(如果无法到达则距离为

分析

好题。

下面令为质数集合。

首先不难发现不可能与其他结点连边,因此直接不管

然后对于点对分情况讨论(设的最小质因子,作为最小质因子在的出现次数):

上述数组可以用一次线性筛处理出来,加上统计时间复杂度仍为

代码

  1. #include<stdio.h>
  2. #define int long long
  3. const int maxn=10000005;
  4. int n,pcnt,all,tot1,tot2,tot3,tot4;
  5. int p[maxn],c[maxn],phi[maxn],cnt[maxn],minn[maxn],sum[maxn];
  6. inline int max(int a,int b){
  7. return a>b? a:b;
  8. }
  9. inline int calc(int l,int r){
  10. return l>r? 0:sum[r]-sum[l-1];
  11. }
  12. signed main(){
  13. scanf("%lld",&n);
  14. c[1]=phi[1]=1;
  15. for(int i=2;i<=n;i++){
  16. if(c[i]==0)
  17. p[++pcnt]=i,minn[i]=i,phi[i]=i-1;
  18. for(int j=1;j<=pcnt;j++){
  19. if(i*p[j]>n)
  20. break;
  21. c[i*p[j]]=1,minn[i*p[j]]=p[j];
  22. if(i%p[j]==0){
  23. phi[i*p[j]]=phi[i]*p[j];
  24. break;
  25. }
  26. phi[i*p[j]]=phi[i]*(p[j]-1);
  27. }
  28. cnt[minn[i]]++;
  29. }
  30. for(int i=1;i<=n;i++)
  31. sum[i]=sum[i-1]+cnt[i];
  32. all=tot1=(n-1)*(n-2)/2;
  33. for(int i=2;i<=n;i++)
  34. tot1-=(phi[i]-1);
  35. for(int i=1;i<=pcnt;i++){
  36. tot3+=cnt[p[i]]*calc(max(n/p[i]+1,p[i]+1),n/2);
  37. tot4+=cnt[p[i]]*calc(max(n/2+1,p[i]+1),n);
  38. }
  39. tot2=(n-1)*(n-2)/2-tot1-tot3-tot4;
  40. printf("%lld\n",tot1*1+tot2*2+tot3*3+tot4*0);
  41. return 0;
  42. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注