题目链接:hdu5212
题目大意:给出n个数a[1]..a[n]求出任意两个数的gcd(a[i], a[j]) * (gcd(a[i], a[j]) - 1)之和。
如果我们枚举k = gcd(a[i], a[j]),那么问题就转化为gcd(a[i], a[j]) = k 的个数,这就是我们熟悉的mobius反演了。跟往常一样,构造F(d),f(d):
f(d) = | {(x, y) | gcd(x, y) == d, x <= N, y <= M} |
F(d) = | {(x, y) | (d | gcd(x, y)), x <= N, y <= M} |
并进行反演,可得:
由于本题中数的范围不是[1..N],而是a[i],因此F(d)需要换一种方法来求得。
我们再来看看F(d)的定义,是所有x,y的公约数(不一定是最大公约数)为d的个数。因此我们仅需要知道a数组中有几个数是d的倍数,设为num[d],则F(d) = num[d] × num[d]
num数组可以O(nlogn)的预处理出来,之后需要枚举最大公约数d求f(d),这个过程也是O(nlogn)。
在求出f(d)之后,将f(d) × d × (d-1)累加即是要求的结果。
事实上,采用dp的方法也可以O(nlogn)的求出f(d)
根据我们在第一个例题中得出的结论,f(d) = F(d) - f(2d) - f(3d) - ……
则可以从后往前扫一遍求出所有的f(d)。
|
|