莫比乌斯反演

hdu 4676 http://acm.hdu.edu.cn/showproblem.php?pid=4676

题意:给你1..n的排列,给一个区间[L,R],返回gcd(a[i],a[j]) L<=i<j<=R的和;

分析:

对于一个区间[L,R],我们设g(d) 表示在区间内gcd(a[i],a[j]) = d的个数 ;

f(d) 表示在区间内gcd(a[i],a[j]) = d的倍数的个数;

显然 f(d) = sigma{ d | n, g(n) };

通过莫比乌斯反演得到  g(d) = sigma{  d | n, mu(n/d) * f(n) };其中mu()是莫比乌斯函数;

g(d) = mu(1) * f(d) + mu(2) * f(2*d) + ... + mu(n/d) * f(n);

设num[d]表示在区间内a[i]是d的倍数的个数;

显然 f(d) = C(num[d] , 2);

那么 ans = 1*g(1) + 2 * g(2) + 3 * g(3) + .. + n * g(n); (最大公约数最大是n);

g(1) = mu(1)*f(1) + mu(2) * f(2) + ... + mu(n) * f(n);

g(2) = mu(1)*f(2) + mu(2) * f(4) + ... + mu(n/2) * f(n);

.....

合并同类项:

ans = sigma( f(d) * w(d) ); 其他w(d) = sigma( a | d , mu(d/a) *a  );

我们可以用nlogn的时间预处理出来w(d); 

这样当我们插入一个数a[k]时,将会使num[d], (d | a[k]) 改变,

这样 ans += (C(num(d)+1,2) - C(num(d),2)) * w(d); 

化简后就是 ans += num(d) * w(d);  

删去一个数类似;

同样我们可以用nlogn的时间预测理出a[k]的因子;

 

最后还有就是分块思想;

 

 

 

posted @ 2013-10-02 22:36  Rabbit_hair  阅读(1567)  评论(0编辑  收藏  举报