题目大意:
给出 n , m n,m n,m,求 ∑ i = 1 n ∑ j = 1 m d ( i ∗ j ) \sum_{i=1}^{n}\sum_{j=1}^{m}d(i*j) ∑i=1n∑j=1md(i∗j), d ( i ∗ j ) 代 表 i ∗ j 的 约 数 个 数 . d(i*j)代表i*j的约数个数. d(i∗j)代表i∗j的约数个数.
T , n , m ≤ 5 e 4 T,n,m \leq 5e4 T,n,m≤5e4
题目思路:
首先得知道一个关于约数个数和的特殊性质:
d
(
i
,
j
)
=
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
y
)
=
=
1
]
d(i,j) = \sum_{x|i}^{}\sum_{y|j}^{}[gcd(x,y)==1]
d(i,j)=∑x∣i∑y∣j[gcd(x,y)==1]
i
i
i的约数A *
j
j
j的约数B
∈
\in
∈
i
∗
j
i*j
i∗j的约数C。
但是直接这样枚举问题是会出现重复的情况.
规定一下:当 C C C的素因子 p p p的指数 小于等于 i i i的素因子 p p p的指数时,从 i i i中拿,否则就取反(全拿走,然后在 j j j中去掉多余的 p p p).这样就保证了一个方案中用C拿出来的 i , j i,j i,j的因子A,B满足 g c d ( A , B ) = 1 gcd(A,B)=1 gcd(A,B)=1.同时,任意一对合法的 A ∗ B A*B A∗B得到的结果 C C C是唯一的。即一一映射。
那么开始推公式了~
原 式 = ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i n ∑ y ∣ j m [ g c d ( x , y ) = = 1 ] 原式=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{x|i}^{n}\sum_{y|j}^{m}[gcd(x,y)==1] 原式=∑i=1n∑j=1m∑x∣in∑y∣jm[gcd(x,y)==1]
经典套路,看不得下面带整除符号,直接换枚举顺序,先枚举约数x,y(由于我们枚举了 x , y , i , j x,y,i,j x,y,i,j,所以上式子的第3/4个求和式就变成了判断式(如下所示))
= ∑ x = 1 n ∑ y = 1 m [ g c d ( x , y ) = = 1 ] ∑ i = 1 n ∑ j = 1 m [ x ∣ i ∧ y ∣ j ] =\sum_{x=1}^{n}\sum_{y=1}^{m}[gcd(x,y)==1]\sum_{i=1}^{n}\sum_{j=1}^{m}[x|i \wedge y|j] =∑x=1n∑y=1m[gcd(x,y)==1]∑i=1n∑j=1m[x∣i∧y∣j]
= ∑ x = 1 n ∑ y = 1 m [ g c d ( x , y ) = = 1 ] ⌊ n x ⌋ ⌊ m y ⌋ =\sum_{x=1}^{n}\sum_{y=1}^{m}[gcd(x,y)==1]\lfloor\frac nx\rfloor\lfloor\frac my\rfloor =∑x=1n∑y=1m[gcd(x,y)==1]⌊xn⌋⌊ym⌋
= ∑ x = 1 n ∑ y = 1 m ∑ d ∣ g c d ( i , j ) μ ( d ) ⌊ n x ⌋ ⌊ m y ⌋ =\sum_{x=1}^{n}\sum_{y=1}^{m}\sum_{d|gcd(i,j)}^{}\mu(d)\lfloor\frac nx\rfloor\lfloor\frac my\rfloor =∑x=1n∑y=1m∑d∣gcd(i,j)μ(d)⌊xn⌋⌊ym⌋
= ∑ d = 1 n μ ( d ) ∑ d ∣ x n ∑ d ∣ y m ⌊ n x ⌋ ⌊ m y ⌋ =\sum_{d=1}^{n}\mu(d)\sum_{d|x}^{n}\sum_{d|y}^{m}\lfloor\frac nx\rfloor\lfloor\frac my\rfloor =∑d=1nμ(d)∑d∣xn∑d∣ym⌊xn⌋⌊ym⌋
= ∑ d = 1 n μ ( d ) ∑ i ⌊ n d ⌋ ∑ j ⌊ m d ⌋ ⌊ n i d ⌋ ⌊ m j d ⌋ =\sum_{d=1}^{n}\mu(d)\sum_{i}^{\lfloor \frac nd \rfloor}\sum_{j}^{\lfloor \frac md \rfloor}\lfloor\frac n{id}\rfloor\lfloor\frac m{jd}\rfloor =∑d=1nμ(d)∑i⌊dn⌋∑j⌊dm⌋⌊idn⌋⌊jdm⌋
= ∑ d = 1 n μ ( d ) ∑ i ⌊ n d ⌋ ⌊ n i d ⌋ ∑ j ⌊ m d ⌋ ⌊ m j d ⌋ =\sum_{d=1}^{n}\mu(d)\sum_{i}^{\lfloor \frac nd \rfloor}\lfloor\frac n{id}\rfloor\sum_{j}^{\lfloor \frac md \rfloor}\lfloor\frac m{jd}\rfloor =∑d=1nμ(d)∑i⌊dn⌋⌊idn⌋∑j⌊dm⌋⌊jdm⌋
预处理莫比乌斯函数和 [ 1 , n ] [1,n] [1,n]的整除分块结果。然后对于每个询问跑一边整除分块即可。
时间复杂度: O ( T n ) O(T\sqrt n) O(Tn)
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vl vector<ll>
#define fi first
#define se second
const int maxn = 5e4 + 5;
const int mod = 1e9 + 7;
int a[maxn];
int bk[maxn] , p[maxn] , cnt , u[maxn];
void init (){
u[1] = 1;
for (int i = 2 ; i < maxn ; i++){
if (!bk[i]){
p[++cnt] = i;
u[i] = -1;
}
for (int j = 1 ; j <= cnt && i * p[j] < maxn ; j++){
bk[i * p[j]] = 1;
if (i % p[j] == 0){
u[i * p[j]] = 0;
break;
}
u[i * p[j]] = -u[i];
}
}
for (int i = 1 ; i < maxn ; i++){
u[i] += u[i - 1];
}
}
ll ff[maxn];
ll f (ll n){
ll ans = 0;
for (ll l = 1 , r; l <= n ; l = r + 1){
r = n / (n / l);
ans += (r - l + 1) * (n / l);
}
return ans;
}
ll solve (ll n , ll m){
ll ans = 0;
for (ll l = 1 , r; l <= n ; l = r + 1){
r = min(n / (n / l) , m / (m / l));
ll a = u[r] - u[l - 1];
ans += a * ff[n / l] * ff[m / l];
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
init();
for (int i = 1 ; i < maxn ; i++){
ff[i] = f(i);
}
int t; cin >> t;
while (t--){
int n , m;
cin >> n >> m;
if (n > m) swap(n , m);
cout << solve(n , m) << endl;
}
return 0;
}