HYSBZ/BZOJ 3994 约数个数和(莫比乌斯反演)

题意

给你n和m求
∑ i = 1 n ∑ j = 1 m d ( i j ) \sum_{i=1}^n\sum_{j=1}^md(ij) i=1nj=1md(ij)
其中 d ( x ) d(x) d(x)表示 x x x约数的个数

思路

这道题其实有一个很神奇的结论
∑ i = 1 n ∑ j = 1 m d ( i j ) = ∑ g c d ( i , j ) = = 1 ⌊ n i ⌋ ⌊ m j ⌋ \sum_{i=1}^n\sum_{j=1}^md(ij)=\sum_{gcd(i,j)==1}\left \lfloor \frac{n}{i} \right \rfloor\left \lfloor \frac{m}{j} \right \rfloor i=1nj=1md(ij)=gcd(i,j)==1injm
∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ m j ⌋ [ g c d ( i , j ) = = 1 ] \sum_{i=1}^n\sum_{j=1}^m\left \lfloor \frac{n}{i} \right \rfloor\left \lfloor \frac{m}{j} \right \rfloor[gcd(i,j)==1] i=1nj=1minjm[gcd(i,j)==1]
那么有了这个式子之后我们就可做了,已知
∑ d ∣ n μ ( d ) = [ n = = 1 ] \sum_{d|n}\mu(d)=[n==1] dnμ(d)=[n==1]
n = g c d ( i , j ) n=gcd(i,j) n=gcd(i,j)带入上式有
∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ⌊ m j ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) \sum_{i=1}^n\sum_{j=1}^m\left \lfloor \frac{n}{i} \right \rfloor\left \lfloor \frac{m}{j} \right \rfloor\sum_{d|gcd(i,j)}\mu(d) i=1nj=1minjmdgcd(i,j)μ(d)
我们改变枚举变量,令 N = m i n ( n , m ) N=min(n,m) N=min(n,m),原来枚举的是 g c d ( i , j ) gcd(i,j) gcd(i,j)的因子,而 g c d ( i , j ) gcd(i,j) gcd(i,j)的范围为 1 ∼ N 1\sim N 1N,相当于枚举 1 ∼ N 1\sim N 1N中每个数的因子,这和枚举 1 ∼ N 1\sim N 1N中每个数的倍数是等价的,故有
= ∑ d = 1 N μ ( d ) ∑ i = 1 n d ⌊ n i d ⌋ ∑ j = 1 m d ⌊ m j d ⌋ =\sum_{d=1}^N\mu(d) \sum_{i=1}^{\frac{n}{d} }\left \lfloor \frac{n}{id} \right \rfloor\sum_{j=1}^{ \frac{m}{d}}\left \lfloor \frac{m}{jd} \right \rfloor =d=1Nμ(d)i=1dnidnj=1dmjdm
我们令 f ( n ) = ∑ i = 1 n ⌊ n i ⌋ f(n)=\sum_{i=1}^{n}\left \lfloor \frac{n}{i} \right \rfloor f(n)=i=1nin
可以看出上式是枚举 1 ∼ n 1\sim n 1n中每个数的倍数有多少个,这个和每个数的约数有多少个是等价的,所以 f ( n ) f(n) f(n)枚举的就是 1 ∼ N 1\sim N 1N中每个数的约数和,那么我们只要筛出每个数的约数个数再做一个前缀和就可以得到 f ( n ) f(n) f(n)
那么原式有
= ∑ d = 1 N μ ( d ) f ( ⌊ n d ⌋ ) f ( ⌊ m d ⌋ ) =\sum_{d=1}^N\mu(d) f(\left \lfloor \frac{n}{d} \right \rfloor)f(\left \lfloor \frac{m}{d} \right \rfloor) =d=1Nμ(d)f(dn)f(dm)
就可以在 O ( n + m ) O(\sqrt{n}+\sqrt{m}) O(n +m )的复杂度下求解了

#include
using namespace std;
const int N=1e6+5;
int d[N];
int prime[N];
int vis[N];
int num[N];
int mu[N];
int cnt;
void init()
{
    cnt=0;
    d[1]=1;
    mu[1]=1;
    for(int i=2;i

你可能感兴趣的:(莫比乌斯反演)