莫比乌斯反演
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]的因子;
最后还有就是分块思想;