这道题就是求:
∑ i = 1 a ∑ j = 1 b [ g c d ( x , y ) = d ] \sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(x,y)=d] ∑ i = 1 a ∑ j = 1 b [ g c d ( x , y ) = d ]
1 ≤ d ≤ a , b ≤ 50000 1\le d\le a,b\le 50000 1 ≤ d ≤ a , b ≤ 50000 。
f ( d ) = ∑ i = 1 a ∑ j = 1 b [ g c d ( i , j ) = d ] f(d)=\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)=d] f ( d ) = ∑ i = 1 a ∑ j = 1 b [ g c d ( i , j ) = d ]
结合莫比乌斯反演:
g ( n ) = ∑ n ∣ k f ( k ) g(n)=\sum_{n|k}f(k) g ( n ) = ∑ n ∣ k f ( k )
f ( n ) = ∑ n ∣ k μ ( k n ) g ( k ) f(n)=\sum_{n|k}\mu(\frac{k}{n})g(k) f ( n ) = ∑ n ∣ k μ ( n k ) g ( k )
我们构造:
g ( n ) = ∑ n ∣ d f ( d ) = ⌊ a n ⌋ ⌊ b n ⌋ g(n)=\sum_{n|d}f(d)=\lfloor\frac{a}{n}\rfloor\lfloor\frac{b}{n}\rfloor g ( n ) = ∑ n ∣ d f ( d ) = ⌊ n a ⌋ ⌊ n b ⌋
这个式子可以直接根据定义去理解,就是所有是 n n n 的倍数的 i i i 和所有是 n n n 的倍数的 j j j 进行组合。
然后我们根据莫比乌斯反演的式子:
f ( d ) = ∑ d ∣ k μ ( k d ) g ( k ) f(d)=\sum_{d|k}\mu(\frac{k}{d})g(k) f ( d ) = ∑ d ∣ k μ ( d k ) g ( k )
然后答案就是:
∑ d ∣ k μ ( k d ) g ( k ) \sum_{d|k}\mu(\frac{k}{d})g(k) ∑ d ∣ k μ ( d k ) g ( k )
∑ d ∣ k μ ( k d ) ⌊ a k ⌋ ⌊ b k ⌋ \sum_{d|k}\mu(\frac{k}{d})\lfloor\frac{a}{k}\rfloor\lfloor\frac{b}{k}\rfloor ∑ d ∣ k μ ( d k ) ⌊ k a ⌋ ⌊ k b ⌋
令 k d \frac{k}{d} d k 为 t t t (整数)。
∑ t = 1 m i n ( a k , b k ) μ ( t ) ⌊ a t d ⌋ ⌊ b t d ⌋ \sum_{t=1}^{min(\frac{a}{k},\frac{b}{k})}\mu(t)\lfloor\frac{a}{td}\rfloor\lfloor\frac{b}{td}\rfloor ∑ t = 1 min ( k a , k b ) μ ( t ) ⌊ t d a ⌋ ⌊ t d b ⌋
然后现在是 O ( n ) O(n) O ( n ) 的,需要继续优化。
然后这个式子就是整除分块的,所以我们使用整除分块。
什么是整除分块?
先看这样一个式子:
∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^{n}\ \lfloor \frac{n}{i} \rfloor i = 1 ∑ n ⌊ i n ⌋
我们发现如果暴力是 O ( n ) O(n) O ( n ) 的,很慢,所以尝试优化。
我们发现这是数学题,尝试打表,对于 n = 10 n=10 n = 10 。
C++ 复制
10
5
3
2
2
1
1
1
1
1
观察一下,我们可以发现这种式子带有很多的相同数字,我们只需要把每一个数字的值乘上个数相加就行了
。稍微想想,会发现:
当 i ≤ n i \le \sqrt{n} i ≤ n 时,i i i 本身只有 n \sqrt{n} n 种可能,因此 ⌊ n i ⌋ \lfloor \frac{n}{i} \rfloor ⌊ i n ⌋ 至多对应 n \sqrt{n} n 个不同的值。
当 i > n i > \sqrt{n} i > n 时,⌊ n i ⌋ < n \lfloor \frac{n}{i} \rfloor < \sqrt{n} ⌊ i n ⌋ < n ,即其取值只能是 1 , 2 , … , ⌊ n ⌋ 1, 2, \dots, \lfloor \sqrt{n} \rfloor 1 , 2 , … , ⌊ n ⌋ ,同样不超过 n \sqrt{n} n 种。
所以复杂度就是根号级别的了。
具体的写法就对于 l l l ,求出数字相同的区间 [ l , r ] [l,r] [ l , r ] ,然后处理完这个区间之后 l = r + 1 l=r+1 l = r + 1 ,进入下一个区间。
回过头来,我们了解了整除分块的思想,看看刚刚的式子:
∑ t = 1 min ( a k , b k ) μ ( t ) ⌊ a t d ⌋ ⌊ b t d ⌋ \sum_{t=1}^{\min(\frac{a}{k},\frac{b}{k})}\mu(t)\lfloor\frac{a}{td}\rfloor\lfloor\frac{b}{td}\rfloor ∑ t = 1 m i n ( k a , k b ) μ ( t ) ⌊ t d a ⌋ ⌊ t d b ⌋
我们只需要找到 ⌊ a t d ⌋ \lfloor\frac{a}{td}\rfloor ⌊ t d a ⌋ 和 ⌊ b t d ⌋ \lfloor\frac{b}{td}\rfloor ⌊ t d b ⌋ 都相同的区间即可。
C++ 复制
void solve(){
int n=min(a/d,b/d);
int ans=0;
for(int l=1,r=0;l<=n;l=r+1){//l <- t
r=min((a/d)/(int)(a/l/d),(b/d)/(int)(b/l/d));
ans+=(sum[r]-sum[l-1])*((a/l/d)*(b/l/d));
}
cout<<ans<<endl;
}