算 术 算术 算术
题目描述见链接 .
正 解 部 分 \color{red}{正解部分} 正解部分
现在要求解 ∑ i = 1 n ∑ j = 1 m μ ( l c m ( i , j ) ) \sum\limits_{i=1}^n\sum\limits_{j=1}^m\mu(lcm(i,j)) i=1∑nj=1∑mμ(lcm(i,j)),
因为 μ ( l c m ( i , j ) ) = μ ( i ) μ ( j ) μ ( g c d ( i , j ) ) \mu(lcm(i,j)) = \mu(i)\mu(j)\mu(gcd(i,j)) μ(lcm(i,j))=μ(i)μ(j)μ(gcd(i,j)),
证 证 证:
假设 μ ( l c m ( i , j ) ) = 0 \mu(lcm(i, j)) = 0 μ(lcm(i,j))=0, 说明 i j g c d ( i , j ) \frac{ij}{gcd(i, j)} gcd(i,j)ij 分解质因数后含有幂数超过 1 1 1 的质因子, 设其为 p p p,
若 p ∣ i p | i p∣i 且 p ∤ j p \not| \ j p∣ j, 则 μ ( i ) = 0 \mu(i)=0 μ(i)=0, 此时上式成立 .
若 p ∣ i p | i p∣i 且 p ∣ j p | j p∣j, 设在 i i i 中 p p p 的幂数为 a a a, j j j 中的幂数为 b b b, 则 a + b − min ( a , b ) > 1 a+b - \min(a, b) > 1 a+b−min(a,b)>1, 令 a > b a > b a>b, 则 a > 1 a > 1 a>1, 此时 μ ( i ) = 0 \mu(i) = 0 μ(i)=0, 此时上式成立 .
假设 μ ( l c m ( i , j ) ) ≠ 0 \mu(lcm(i, j)) \not= 0 μ(lcm(i,j))=0, 则幂数相加的奇偶性与幂数相减的奇偶性相同, 不会改变 μ \mu μ 取值, 上式成立 .
∴ 综 上 所 述 , 上 式 成 立 \therefore 综上所述, 上式成立 ∴综上所述,上式成立
所以原式
∑
i
=
1
n
∑
j
=
1
m
μ
(
i
)
μ
(
j
)
μ
(
g
c
d
(
i
,
j
)
)
\sum\limits_{i=1}^n\sum\limits_{j=1}^m \mu(i)\mu(j)\mu(gcd(i,j))
i=1∑nj=1∑mμ(i)μ(j)μ(gcd(i,j)),
枚举
d
=
g
c
d
(
i
,
j
)
d = gcd(i, j)
d=gcd(i,j) 得
∑ d = 1 min ( n , m ) μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ μ ( i d ) μ ( j d ) [ g c d ( i , j ) = = 1 ] \sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}\mu(id)\mu(jd)[gcd(i,j)==1] d=1∑min(n,m)μ(d)i=1∑⌊dn⌋j=1∑⌊dm⌋μ(id)μ(jd)[gcd(i,j)==1]
根据 这里 所述的 μ \mu μ 性质 2 2 2,
∑ d = 1 min ( n , m ) μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ μ ( i d ) μ ( j d ) ∑ k ∣ g c d ( i , j ) μ ( k ) \sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}\mu(id)\mu(jd)\sum\limits_{k|gcd(i,j)} \mu(k) d=1∑min(n,m)μ(d)i=1∑⌊dn⌋j=1∑⌊dm⌋μ(id)μ(jd)k∣gcd(i,j)∑μ(k)
∑ d = 1 min ( n , m ) μ ( d ) ∑ k = 1 ⌊ min ( n , m ) d ⌋ μ ( k ) ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ m k d ⌋ μ ( i d k ) μ ( j d k ) \sum\limits_{d=1}^{\min(n, m)}\mu(d) \sum\limits_{k=1}^{\lfloor \frac{\min(n, m)}{d} \rfloor } \mu(k) \sum\limits_{i=1}^{\lfloor \frac{n}{kd} \rfloor} \sum\limits_{j=1}^{\lfloor \frac{m}{kd} \rfloor} \mu(idk)\mu(jdk) d=1∑min(n,m)μ(d)k=1∑⌊dmin(n,m)⌋μ(k)i=1∑⌊kdn⌋j=1∑⌊kdm⌋μ(idk)μ(jdk)
设 T = d k T = dk T=dk,
∑ T = 1 min ( n , m ) ∑ d ∣ T μ ( d ) μ ( T d ) ∑ i = 1 ⌊ n T ⌋ μ ( i T ) ∑ j = 1 ⌊ m T ⌋ μ ( j T ) \sum\limits_{T=1}^{\min(n,m)}\sum\limits_{d\mid T}\mu(d)\mu(\frac{T}{d})\sum\limits_{i=1}^{\lfloor\frac{n}{T}\rfloor}\mu(iT)\sum\limits_{j=1}^{\lfloor\frac{m}{T}\rfloor}\mu(jT) T=1∑min(n,m)d∣T∑μ(d)μ(dT)i=1∑⌊Tn⌋μ(iT)j=1∑⌊Tm⌋μ(jT)
实 现 部 分 \color{red}{实现部分} 实现部分
预处理括号内元素即可实现 O ( N log N ) O(N\log N) O(NlogN) 计算答案 .
∑ T = 1 min ( n , m ) ( ∑ d ∣ T μ ( d ) μ ( T d ) ) ( ∑ i = 1 ⌊ n T ⌋ μ ( i T ) ) ( ∑ j = 1 ⌊ m T ⌋ μ ( j T ) ) \sum\limits_{T=1}^{\min(n,m)} \left(\sum\limits_{d\mid T}\mu(d)\mu(\frac{T}{d}) \right) \left(\sum\limits_{i=1}^{\lfloor\frac{n}{T}\rfloor}\mu(iT) \right) \left(\sum\limits_{j=1}^{\lfloor\frac{m}{T}\rfloor}\mu(jT)\right) T=1∑min(n,m)(d∣T∑μ(d)μ(dT))(i=1∑⌊Tn⌋μ(iT))(j=1∑⌊Tm⌋μ(jT))
#include<bits/stdc++.h>
#define reg register
typedef long long ll;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1e6 + 5;
const int lim = 1e6;
int N;
int M;
int pc;
int p[maxn];
int mu[maxn];
int s2[maxn];
int s3[maxn];
int vis[maxn];
int s1[maxn+1];
void Init(){
mu[1] = 1;
for(reg int i = 2; i <= lim; i ++){
if(!vis[i]) p[++ pc] = i, mu[i] = -1;
for(reg int j = 1; j <= pc && p[j]*i <= lim; j ++){
vis[p[j]*i] = 1;
if(i % p[j] == 0){ mu[p[j]*i] = 0; break ; }
mu[p[j]*i] = -mu[i];
}
}
for(reg int i = 1; i <= lim; i ++)
for(reg int j = 1; j <= lim/i; j ++) s1[i*j] += mu[i] * mu[j];
}
void Work(){
memset(s2, 0, sizeof s2); memset(s3, 0, sizeof s3);
N = read(), M = read();
for(reg int i = 1; i <= N; i ++)
for(reg int j = 1; j <= N/i; j ++) s2[i] += mu[i * j];
for(reg int i = 1; i <= M; i ++)
for(reg int j = 1; j <= M/i; j ++) s3[i] += mu[i * j];
N = std::min(N, M);
ll Ans = 0;
for(reg int i = 1; i <= N; i ++) Ans += 1ll*s1[i]*s2[i]*s3[i];
printf("%lld\n", Ans);
}
int main(){
Init();
int test_cnt = read();
while(test_cnt --) Work();
return 0;
}