失踪OJ回归。

  毕竟这样的数论没做过几道,碰上一些具体的应用还是无所适从啊。小C还是借助这题大致摸索一下莫比乌斯函数吧。

Description

  有n个点,标号为1~n,为这n个点建一张无向图。两个点x,y之间有连边当且仅当x,y不互质,求两两点对之间的最短路d(x,y)(1<=x<y<=n)之和。(如果两个点不连通,令它们之间的最短路为0)

Input

  只有一行,一个正整数n。

Output

  输出两两点对之间的最短路之和。

Sample Input

  10

Sample Output

  44

HINT

  1<=n<=10^7。

Solution

  通过仔细思考,1对答案没有贡献,我们不考虑1。设low[x]为x的最小质因数,我们可以把点对(x,y)之间的关系分为四种:

  ①gcd(x,y)>1:d(x,y)=1;

  ②gcd(x,y)=1且low[x]*low[y]<=n:d(x,y)=d(x,low[x]*low[y])+d(low[x]*low[y],y)=2;

  ③gcd(x,y)=1且low[x]*low[y]>n且low[x]*2<=n且low[y]*2<=n:d(x,y)=d(x,low[x]*2)+d(low[x]*2,low[y]*2)+d(low[y]*2,y)=3;

  ④gcd(x,y)=1且low[x]*2>n或low[y]*2>n:d(x,y)=0。

  其中第一种和第四种都很好处理,第一种用欧拉函数,第四种求出每个数的最小质因数,统计一下low[x]>n/2的个数计算即可。

  用所有方案数减去第一种和第四种的方案数就是第二和第三种的方案数和。

  接下来的任务,就是求出第二种或第三种其中一种情况的方案数即可。第二种似乎看起来比第三种好求。

  很自然地,我们想到对于每个low[x]统计x的个数。因此对于每个low[x]用二分或指针法加上前缀和就可以分别计算答案。

  然而这个统计方法显然是有重复的。因为这样把gcd不为1的对数也算进去了,且每对这样的x,y恰好被算了一次。

  所以现在我们要统计的是:gcd(x,y)>1且low[x]*low[y]<=n的x,y对数。

  所以我们似乎可以枚举gcd(x,y),统计这样的x,y对数?但显然枚举gcd太难受了,枚举公因数还是更容易一些。

  所以每对满足gcd(x,y)>1的x,y被算了 gcd(x,y)的因数个数 次!

  怎么才能让每对满足x,y被算了 gcd(x,y)的因数个数 次后相当于只被算了一次呢?容斥?怎么容斥?

  然后我们就想到了莫比乌斯反演中的

  由于我们并没有考虑1,因此,正好就是我们所想要求的啊!

  所以现在我们求的是

  我们枚举i,对于每个i考虑怎么计算x,y的对数。

  当时,low[x]*low[y]无论如何都不会大于n,所以这样的x,y对数为(n/i)*(n/i)。

  当时,low[x]*low[y]只有当x=y=i且i为质数的时候才会大于n,当满足这种情况时减去1即可。

  所以我们就完成了这漫长的计算,时间复杂度O(n)。

#include <algorithm>
#include <cstring>
#include <cstdio>
#define ll long long
#define MN 10000005
using namespace std;
int n,prin,dys;
int zx[MN],pri[MN],phi[MN],miu[MN],sm[MN];
ll ans,sum; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} int main()
{
register int i,j;
n=read();
for (phi[]=miu[]=,i=;i<=n;++i)
{
if (!zx[i]) pri[++prin]=i,zx[i]=prin,phi[i]=i-,miu[i]=-;
for (j=;i*pri[j]<=n;++j)
{
zx[i*pri[j]]=j;
if (i%pri[j]==) {phi[i*pri[j]]=phi[i]*pri[j]; miu[i*pri[j]]=; break;}
else {phi[i*pri[j]]=phi[i]*(pri[j]-); miu[i*pri[j]]=-miu[i];}
}
ans+=i-phi[i]-; ++sm[zx[i]];
}
for (i=;i<=prin;++i) if (pri[i]*>n) ++dys;
ans+=(1LL*(n-)*(n-)/-ans-1LL*dys*(n-dys-)-1LL*dys*(dys-)/)*;
for (i=;i<=prin;++i) sm[i]+=sm[i-];
for (i=,j=prin;i<=prin;++i)
{
for (;j&&pri[i]*pri[j]>n;--j);
sum+=1LL*sm[j]*(sm[i]-sm[i-]);
}
for (i=;i<=n;++i) sum+=(1LL*(n/i)*(n/i)-(pri[zx[i]]==i&&1LL*i*i>n))*miu[i];
printf("%I64d",ans-sum/);
}

Last Word

  这其中的计算思路还真是令人捉摸不透啊,各个计算之间的关联度很小,很显然需要很多碎片化的思路拼接起来才能完成这道题。

  莫比乌斯函数其实就是通过枚举因数来进行的容斥吧。

[Codeforces]871D Paths的更多相关文章

  1. Codeforces.871D.Paths(莫比乌斯反演 根号分治)

    题目链接 \(Description\) 给定\(n\),表示有一张\(n\)个点的无向图,两个点\(x,y\)之间有权值为\(1\)的边当且仅当\(\gcd(x,y)\neq1\).求\(1\sim ...

  2. Codeforces 871D Paths (欧拉函数 + 结论)

    题目链接  Round  #440  Div 1  Problem D 题意   把每个数看成一个点,如果$gcd(x, y) \neq 1$,则在$x$和$y$之间连一条长度为$1$的无向边.   ...

  3. Codeforces 545E. Paths and Trees 最短路

    E. Paths and Trees time limit per test: 3 seconds memory limit per test: 256 megabytes input: standa ...

  4. [Codeforces 545E] Paths and Trees

    [题目链接] https://codeforces.com/contest/545/problem/E [算法] 首先求 u 到所有结点的最短路 记录每个节点最短路径上的最后一条边         答 ...

  5. codeforces 792D - Paths in a Complete Binary Tree

    #include<cstdio> #include<iostream> #define lowbit(x) x&(-x) typedef long long ll; u ...

  6. Codeforces 545E. Paths and Trees[最短路+贪心]

    [题目大意] 题目将从某点出发的所有最短路方案中,选择边权和最小的最短路方案,称为最短生成树. 题目要求一颗最短生成树,输出总边权和与选取边的编号.[题意分析] 比如下面的数据: 5 5 1 2 2 ...

  7. [codeforces 293]B. Distinct Paths

    [codeforces 293]B. Distinct Paths 试题描述 You have a rectangular n × m-cell board. Some cells are alrea ...

  8. Codeforces Beta Round #14 (Div. 2) D. Two Paths 树形dp

    D. Two Paths 题目连接: http://codeforces.com/contest/14/problem/D Description As you know, Bob's brother ...

  9. codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)

    codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

随机推荐

  1. 20145237 《Java程序设计》第三周学习总结

    20145237 <Java程序设计>第3周学习总结 教材学习内容总结 第四章主要讲了Java基本类型中的类类型,如何定义类.构造函数.使用标准类.基本类型打包器.数组复制.字符串等内容查 ...

  2. 201421123042 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1. List中指定元素的删除(题集题目) 1.1 实验总结.并回答:列举至 ...

  3. webview缓存及跳转时截取url地址、监听页面变化

    缓存及一些设定 我在做一些项目时,h5做的项目手机浏览器能使用,但是在搬到webview时候不能用,这个时候通过查阅资料,原来是webview没有设定好,包括缓存.缓存大小及路径等等 mWebview ...

  4. raid5 阵列硬盘离线数据恢复成功案例

    数据恢复故障描述: 某研究院 DELL 磁盘阵列崩溃,内置15块1TB硬盘搭建的RAID5阵列.一开始有一块硬盘离线,在更换新硬盘进行同步的过程中,第二块磁盘指示灯报警,同步失败,阵列无法正常工作. ...

  5. 用anaconda安装最新的TensorFlow版本

    Google发布了TensorFlow1.4正式版 在anaconad搜索依旧是1.2的版本,通过一番查阅,找到了方法 1,打开anaconda-prompt 2,激活你要安装的环境 activate ...

  6. Python内置函数(25)——frozenset

    英文文档: class frozenset([iterable]) Return a new frozenset object, optionally with elements taken from ...

  7. unity A*寻路 (三)A*算法

    这里我就不解释A*算法 如果你还不知道A*算法 网上有很多简单易懂的例子 我发几个我看过的链接 http://www.cnblogs.com/lipan/archive/2010/07/01/1769 ...

  8. GIT入门笔记(11)- 多种撤销修改场景和对策--实战练习

    1.检查发现目前没有变化$ git statusOn branch masternothing to commit, working tree clean $ cat lsq.txt2222 2.修改 ...

  9. 阿里云API网关(12)为员工创建子账号,实现分权管理API:使用RAM管理API

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  10. POJ1236【Tarjan+缩点】

    题目大意:有向关系体现在电脑可以通过网络单向的传输文件,并规定一旦有电脑存在该文件,那么所有它能传输的电脑就能在第一时间得到这个文件,题目有两个问题,第一个是最少向网络中的几台电脑投放文件,能使得整个 ...