文章目录
寒假疫情期间跟着lmm学了一遍,完全是懵逼到底状态,以至于后面考到或者做到相关知识的题目,完全是非洲人。今天跟着h老师重新学了一遍,虽然可能自己还是不会推🍔,但至少看得懂了吧
莫比乌斯反演
莫比乌斯反演形式的式子形如 F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum_{d|n}f(d) F(n)=∑d∣nf(d),一般而言 F ( n ) F(n) F(n) 是非常好求的,而 f ( x ) f(x) f(x) 即为要求的信息。
引入
F
(
n
)
=
∑
d
∣
n
f
(
d
)
F(n)=\sum_{d|n}f(d)
F(n)=d∣n∑f(d)
通过这个例子,可以暴力打出下列表
F ( 1 ) F(1) F(1) | f ( 1 ) f(1) f(1) |
---|---|
F ( 2 ) F(2) F(2) | f ( 1 ) + f ( 2 ) f(1)+f(2) f(1)+f(2) |
F ( 3 ) F(3) F(3) | f ( 1 ) + f ( 3 ) f(1)+f(3) f(1)+f(3) |
F ( 4 ) F(4) F(4) | f ( 1 ) + f ( 2 ) + f ( 4 ) f(1)+f(2)+f(4) f(1)+f(2)+f(4) |
F ( 5 ) F(5) F(5) | f ( 1 ) + f ( 5 ) f(1)+f(5) f(1)+f(5) |
F ( 6 ) F(6) F(6) | f ( 1 ) + f ( 2 ) + f ( 3 ) + f ( 6 ) f(1)+f(2)+f(3)+f(6) f(1)+f(2)+f(3)+f(6) |
F ( 7 ) F(7) F(7) | f ( 1 ) + f ( 7 ) f(1)+f(7) f(1)+f(7) |
F ( 8 ) F(8) F(8) | f ( 1 ) + f ( 2 ) + f ( 4 ) + f ( 8 ) f(1)+f(2)+f(4)+f(8) f(1)+f(2)+f(4)+f(8) |
… | … |
转换一下,得到新表
f ( 1 ) f(1) f(1) | F ( 1 ) F(1) F(1) |
---|---|
f ( 2 ) f(2) f(2) | F ( 2 ) − F ( 1 ) F(2)-F(1) F(2)−F(1) |
f ( 3 ) f(3) f(3) | F ( 3 ) − F ( 1 ) F(3)-F(1) F(3)−F(1) |
f ( 4 ) f(4) f(4) | F ( 4 ) − F ( 2 ) F(4)-F(2) F(4)−F(2) |
f ( 5 ) f(5) f(5) | F ( 5 ) − F ( 1 ) F(5)-F(1) F(5)−F(1) |
f ( 6 ) f(6) f(6) | F ( 6 ) − F ( 3 ) − F ( 2 ) + F ( 1 ) F(6)-F(3)-F(2)+F(1) F(6)−F(3)−F(2)+F(1) |
f ( 7 ) f(7) f(7) | F ( 7 ) − F ( 1 ) F(7)-F(1) F(7)−F(1) |
f ( 8 ) f(8) f(8) | F ( 8 ) − F ( 4 ) F(8)-F(4) F(8)−F(4) |
… | … |
看看能观察到
f
f
f与
F
F
F之间存在什么规律??
🚨 重点关注
f
(
1
)
,
f
(
4
)
,
f
(
6
)
,
f
(
8
)
f(1),f(4),f(6),f(8)
f(1),f(4),f(6),f(8)
🧀
f
(
6
)
=
F
(
6
1
)
−
F
(
6
2
)
−
F
(
6
3
)
+
F
(
6
6
)
f(6)=F(\frac{6}{1})-F(\frac{6}{2})-F(\frac{6}{3})+F(\frac{6}{6})
f(6)=F(16)−F(26)−F(36)+F(66)
发现规律 其实是知道公式了
F ( n d ) F(\frac{n}{d}) F(dn)将 d d d质因数分解 p 1 k 1 . . . p i k i p_1^{k_1}...p_i^{k_i} p1k1...piki,如果各质数指数均为 1 1 1,则该 F ( n d ) F(\frac{n}{d}) F(dn)才会存在 ,特别地,当 d = 1 d=1 d=1时也一定存在
🍗:
f
(
8
)
=
F
(
8
1
)
−
F
(
8
2
)
f(8)=F(\frac{8}{1})-F(\frac{8}{2})
f(8)=F(18)−F(28)
F
(
8
1
)
:
1
F(\frac{8}{1}):1
F(18):1存在
F
(
8
2
)
:
2
F(\frac{8}{2}):2
F(28):2质因数分解
2
1
2^1
21,存在
F
(
2
)
=
F
(
8
4
)
:
4
F(2)=F(\frac{8}{4}):4
F(2)=F(48):4质因数分解
2
2
2^2
22,不存在
F
(
1
)
=
F
(
8
8
)
:
8
F(1)=F(\frac{8}{8}):8
F(1)=F(88):8质因数分解
2
3
2^3
23,不存在
F ( n d ) F(\frac{n}{d}) F(dn)前面的符号取决于 d d d所含质因子的个数/种类的奇偶性, ( − 1 ) k (-1)^k (−1)k
🍗:
f
(
6
)
=
F
(
6
1
)
−
F
(
6
2
)
−
F
(
6
3
)
+
F
(
6
6
)
f(6)=F(\frac{6}{1})-F(\frac{6}{2})-F(\frac{6}{3})+F(\frac{6}{6})
f(6)=F(16)−F(26)−F(36)+F(66)
F
(
6
1
)
:
1
F(\frac{6}{1}):1
F(16):1不含任何质因子,系数为
(
−
1
)
0
=
1
(-1)^0=1
(−1)0=1
F
(
6
2
)
:
2
F(\frac{6}{2}):2
F(26):2含质因子
2
2
2,系数为
(
−
1
)
1
=
−
1
(-1)^1=-1
(−1)1=−1
F
(
6
3
)
:
3
F(\frac{6}{3}):3
F(36):3含质因子
3
3
3,系数为
(
−
1
)
1
=
−
1
(-1)^1=-1
(−1)1=−1
F
(
6
6
)
:
6
F(\frac{6}{6}):6
F(66):6含质因子
2
,
3
2,3
2,3,系数为
(
−
1
)
2
=
1
(-1)^2=1
(−1)2=1
公式
将引入中发现的规律经过数学 提炼加工打磨 规范,将
(
−
1
)
k
(-1)^k
(−1)k定义为
μ
(
i
)
\mu (i)
μ(i)
便成为了一个优美的🍔
F
(
n
)
=
∑
d
∣
n
f
(
n
)
⇒
f
(
n
)
=
∑
d
∣
n
μ
(
d
)
F
(
n
d
)
F(n)=\sum_{d|n}f(n)\Rightarrow f(n)=\sum_{d|n}\mu (d)F(\frac{n}{d})
F(n)=d∣n∑f(n)⇒f(n)=d∣n∑μ(d)F(dn)
其中 μ ( d ) \mu(d) μ(d)为莫比乌斯函数,定义如下:
- d = 1 , μ ( d ) = 1 d=1,\mu(d)=1 d=1,μ(d)=1
- 若 d d d能改写为 p 1 p 2 . . . p k p_1p_2...p_k p1p2...pk互异质数的积,则 μ ( d ) = ( − 1 ) k \mu(d)=(-1)^k μ(d)=(−1)k
- o t h e r w i s e otherwise otherwise,其余情况 μ ( d ) = 0 \mu(d)=0 μ(d)=0
性质
- 性质一:
对于任意的正整数 n n n有:
∑ d ∣ n μ ( d ) = { 1 ( n = 1 ) 0 ( n ≠ 1 ) \sum_{d|n}\mu(d)=\left\{ \begin{aligned} 1&&(n=1)\\ 0&&(n≠1) \end{aligned} \right. d∣n∑μ(d)={10(n=1)(n=1)
证明:
Ⅰ. 当 n = 1 n=1 n=1时, μ ( 1 ) = 1 \mu(1)=1 μ(1)=1,显然成立
Ⅱ. 当 n ≠ 1 n≠1 n=1时,将 n n n质因数分解为 p 1 a 1 p 2 a 2 . . . p k a i p_1^{a_1}p_2^{a_2}...p_k^{a_i} p1a1p2a2...pkai
只有所有质因子的指数都为 1 1 1的因数的 μ \mu μ值不为 0 0 0
则其中有 x x x个不同质因子的个数为 C k x C_k^x Ckx,于是有
∑ d ∣ n μ ( d ) = C k 0 − C k 1 + C k 2 . . . . = ∑ i = 0 k ( − 1 ) i C k i \sum_{d|n}\mu(d)=C_k^0-C_k^1+C_k^2....=\sum_{i=0}^k(-1)^iC_k^i d∣n∑μ(d)=Ck0−Ck1+Ck2....=i=0∑k(−1)iCki
🧀二项式展开公式为:
( X + Y ) n = ∑ i = 0 n C n i X i Y n − i (X+Y)^n=\sum_{i=0}^nC_n^iX^iY^{n-i} (X+Y)n=i=0∑nCniXiYn−i
令 X = 1 , Y = − 1 X=1,Y=-1 X=1,Y=−1带入即可得到:
∑ i = 0 k ( − 1 ) i C k i = [ 1 + ( − 1 ) ] k = 0 \sum_{i=0}^k(-1)^iC_k^i=[1+(-1)]^k=0 i=0∑k(−1)iCki=[1+(−1)]k=0
- 性质二:
对于任意的正整数 n n n有:
∑ d ∣ n μ ( d ) d = ϕ ( n ) n \sum_{d|n}\frac{\mu(d)}{d}=\frac{\phi(n)}{n} d∣n∑dμ(d)=nϕ(n)
证明:
∑ d ∣ n μ ( d ) d = ϕ ( n ) n ⇔ n × ∑ d ∣ n μ ( d ) d = ϕ ( n ) \sum_{d|n}\frac{\mu(d)}{d}=\frac{\phi(n)}{n}\Leftrightarrow n\times \sum_{d|n}\frac{\mu(d)}{d}=\phi(n) d∣n∑dμ(d)=nϕ(n)⇔n×d∣n∑dμ(d)=ϕ(n)
令 F ( n ) = n , f ( n ) = ϕ ( n ) F(n)=n,f(n)=\phi(n) F(n)=n,f(n)=ϕ(n),则有
f ( n ) = n × ∑ d ∣ n μ ( d ) d = ∑ d ∣ n μ ( d ) n d = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=n\times \sum_{d|n}\frac{\mu(d)}{d}=\sum_{d|n}\mu(d)\frac{n}{d}=\sum_{d|n}\mu(d)F(\frac{n}{d}) f(n)=n×d∣n∑dμ(d)=d∣n∑μ(d)dn=d∣n∑μ(d)F(dn)
🚨不要忘记 f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d}) f(n)=∑d∣nμ(d)F(dn)成立的前提是 F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum_{d|n}f(d) F(n)=∑d∣nf(d)
所以如果性质二要想成立,就必须再证明 n = ∑ d ∣ n ϕ ( d ) n=\sum_{d|n}\phi(d) n=d∣n∑ϕ(d)
考虑从物理意义角度出发
设 k ∈ [ 1 , n ] , g c d ( n , k ) = d ⇒ g c d ( n / d , k ) = 1 k∈[1,n],gcd(n,k)=d\Rightarrow gcd(n/d,k)=1 k∈[1,n],gcd(n,k)=d⇒gcd(n/d,k)=1,将 k k k分到 C n / d C_{n/d} Cn/d类中
🍗: n = 8 n=8 n=8
{ 1 , 3 , 5 , 7 g c d = 1 ϕ ( 8 1 ) = 4 2 , 6 g c d = 2 ϕ ( 8 2 ) = 2 4 g c d = 4 ϕ ( 8 4 ) = 1 8 g c d = 8 ϕ ( 8 8 ) = 1 \left\{ \begin{aligned} 1,3,5,7&&gcd=1&&\phi(\frac{8}{1})=4\\ 2,6&&gcd=2&&\phi(\frac{8}{2})=2\\ 4&&gcd=4&&\phi(\frac{8}{4})=1\\ 8&&gcd=8&&\phi(\frac{8}{8})=1 \end{aligned} \right. ⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧1,3,5,72,648gcd=1gcd=2gcd=4gcd=8ϕ(18)=4ϕ(28)=2ϕ(48)=1ϕ(88)=1
- 性质三:
莫比乌斯函数是一个积性函数
但我不会证明
🧀
积性函数的定义:对于任意互质的整数 a a a和 b b b有性质 f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b)的数论函数
完全积性函数定义:对于任意的整数 a a a和 b b b有 f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b)的数论函数
积性函数的性质:
- f ( 1 ) = 1 f(1)=1 f(1)=1
- 积性函数的前缀和也是积性函数
模板
因为莫比乌斯函数是一个积性函数,我们就可以线性筛求出其值
由此联想到我们以前会的求质数的欧拉筛法
void sieve() {
mu[1] = 1;
for( int i = 2;i <= n;i ++ ) {
if( ! vis[i] ) {
vis[i] = 1;
mu[i] = -1;
prime[++ cnt] = i;
}
for( int j = 1;j <= cnt && i * prime[j] <= n;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0; //i*prime[j]这个数至少含有prime[j]^2
break;
}
mu[i * prime[j]] = - mu[i];//多了prime[j]这一种新的质因子 所以要与原来取相反数
/*
只要i*prime[j]含有pi^2
早晚都会进if语句
*/
}
}
}
公式证明
说到底,好像我们似乎貌似仿佛并没有证明这个定理,就直接提上裤子跑了
- 形式一
证明:
F ( n ) = ∑ d ∣ n f ( n ) ⇒ f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) = ∑ d ∣ n μ ( d ) ∑ k ∣ n d f ( k ) F(n)=\sum_{d|n}f(n)\Rightarrow f(n)=\sum_{d|n}\mu (d)F(\frac{n}{d})=\sum_{d|n}\mu(d)\sum_{k|\frac{n}{d}}f(k) F(n)=d∣n∑f(n)⇒f(n)=d∣n∑μ(d)F(dn)=d∣n∑μ(d)k∣dn∑f(k)
d ∣ n , k ∣ n d ⇒ k ∣ n {d|n,k|\frac{n}{d}\Rightarrow k|n} d∣n,k∣dn⇒k∣n,可以感性理解 d d d取不同值, k k k会把 n n n所有因数都枚举到
于是可以把 k k k固定下来,更改 d d d的取值范围,类似于两层循环顺序的互调??
=
∑
k
∣
n
f
(
k
)
∑
d
∣
n
k
μ
(
d
)
=\sum_{k|n}f(k)\sum_{d|\frac{n}{k}}\mu(d)
=k∣n∑f(k)d∣kn∑μ(d)
将性质一的结论运用上,
∑
d
∣
n
k
μ
(
d
)
\sum_{d|\frac{n}{k}}\mu(d)
∑d∣knμ(d)当且仅当
n
k
=
1
\frac{n}{k}=1
kn=1时,求和莫比乌斯函数值
≠
0
≠0
=0
=
f
(
n
)
=f(n)
=f(n)
证明过程用到了性质一,性质一本身其实是独立于公式的,所以并不是伪证
- 形式二
F ( n ) = ∑ n ∣ d f ( d ) ⇒ f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) F(n)=\sum_{n|d}f(d)\Rightarrow f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d) F(n)=n∣d∑f(d)⇒f(n)=n∣d∑μ(nd)F(d)
证明:
与形式一的证明大致相同
令 k = d n k=\frac{d}{n} k=nd
= ∑ k = 1 + ∞ μ ( k ) F ( n × k ) = ∑ k = 1 + ∞ μ ( k ) ∑ n × k ∣ p f ( p ) = ∑ n ∣ p f ( p ) ∑ k ∣ p n μ ( k ) =\sum_{k=1}^{+∞}\mu(k)F(n\times k)=\sum_{k=1}^{+∞}\mu(k)\sum_{n\times k|p}f(p)=\sum_{n|p}f(p)\sum_{k|\frac{p}{n}}\mu(k) =k=1∑+∞μ(k)F(n×k)=k=1∑+∞μ(k)n×k∣p∑f(p)=n∣p∑f(p)k∣np∑μ(k)
当且仅当
p
n
=
1
,
p
=
n
\frac{p}{n}=1,p=n
np=1,p=n时
∑
k
∣
n
p
μ
(
k
)
=
1
\sum_{k|\frac{n}{p}}\mu(k)=1
∑k∣pnμ(k)=1,其余全为
0
0
0
=
f
(
n
)
=f(n)
=f(n)
一般这种形式更常用一些
莫比乌斯函数前缀和
基本上莫比乌斯反演的题目都会和分块绑定在一起,此时的莫比乌斯函数就需要进行前缀和
接下来就让我们一起来深挖一下分块部分
🍗
Q
=
∑
i
∣
d
μ
(
i
)
⌊
n
i
⌋
Q=\sum_{i|d}\mu(i)\lfloor{\frac{n}{i}}\rfloor
Q=i∣d∑μ(i)⌊in⌋
不妨设
n
=
10
n=10
n=10,如果按照
⌊
n
i
⌋
\lfloor{\frac{n}{i}}\rfloor
⌊in⌋对
1
≤
i
≤
n
1\le i\le n
1≤i≤n进行分类
则有
10
=
{
1
}
,
5
=
{
2
}
,
3
=
{
3
}
,
2
=
{
4
,
5
}
,
1
=
{
6
,
7
,
8
,
9
,
10
}
10=\{1\},5=\{2\},3=\{3\},2=\{4,5\},1=\{6,7,8,9,10\}
10={1},5={2},3={3},2={4,5},1={6,7,8,9,10}
反映在平面直角坐标系上,看看是什么样👀
按照
x
\sqrt{x}
x做分割线,前半段的
x
x
x最多只有
x
\sqrt{x}
x段,后半段的
y
y
y最多只有
x
\sqrt{x}
x段
拼接在一起,则
⌊
n
i
⌋
\lfloor{\frac{n}{i}}\rfloor
⌊in⌋最多只有
2
n
2\sqrt{n}
2n个取值
n
/
i
n/i
n/i即为
i
i
i所在的块,
n
/
(
n
/
i
)
n/(n/i)
n/(n/i)则为该块右端点值
block = n / i;
r = n / block;
因为
[
i
,
n
/
(
n
/
i
)
]
[i,n/(n/i)]
[i,n/(n/i)]这一段的
⌊
n
i
⌋
\lfloor{\frac{n}{i}}\rfloor
⌊in⌋均相等
所以我们就可以对
μ
\mu
μ进行前缀和,直接
O
(
1
)
O(1)
O(1)计算出这一段区间的
s
u
m
sum
sum
就不必再老实地一个一个往后推
老实人永远会被出题人吊起来抽
这个思想会在后面的题里反复出现,所以提前放出来
一般情况下,莫比乌斯反演后都是求 f ( 1 ) f(1) f(1) 因为这个时候 f ( 1 ) = ∑ i = 1 i n f μ ( i ) F ( i ) f(1)=\sum_{i=1}^{inf}\mu(i)F(i) f(1)=∑i=1infμ(i)F(i) 才能连续地整除分块。
i n f inf inf 是取决于 F F F 函数在什么时候开始就一直取值为 0 0 0,后面的信息没有贡献即可停止枚举。
题目练习
完全平方数
- solution
考虑二分答案,转化为求
[
1
,
x
]
[1,x]
[1,x]之间的无平方因子的个数
t
o
t
=
0
tot=0
tot=0个质数乘积的平方的倍数的数的个数(
1
1
1的倍数)
−
1
-1
−1个质数乘积的平方的倍数的数的个数(
4
[
2
2
]
4[2^2]
4[22]的倍数,
9
[
3
2
]
9[3^2]
9[32]的倍数…)
+
2
+2
+2个质数乘积的平方的倍数的数的个数(
36
[
(
2
×
3
)
2
]
36[(2\times 3)^2]
36[(2×3)2]的倍数…)
发现每个乘积前面的系数刚好是
μ
(
i
)
\mu(i)
μ(i)
🍗:
μ
(
3
)
=
−
1
\mu(3)=-1
μ(3)=−1,故
9
9
9对答案的贡献为负,
μ
(
6
)
=
1
\mu(6)=1
μ(6)=1,故
36
36
36对答案的贡献为正
x
x
x以内的
i
2
i^2
i2的个数为
x
i
2
\frac{x}{i^2}
i2x
⇒
t
o
t
(
x
)
=
∑
i
=
1
x
μ
(
i
)
x
i
2
\Rightarrow tot(x)=\sum_{i=1}^{\sqrt{x}}\mu(i)\frac{x}{i^2}
⇒tot(x)=i=1∑xμ(i)i2x
这道题仅是莫比乌斯函数的运用,并非莫比乌斯反演
- code
#include <cstdio>
#define int long long
#define maxn 1000005
int T, k, cnt;
int mu[maxn], prime[maxn];
bool vis[maxn];
void init() {
mu[1] = 1;
for( int i = 2;i < maxn;i ++ ) {
if( ! vis[i] ) mu[i] = -1, prime[++ cnt] = i;
for( int j = 1;j <= cnt && i * prime[j] < maxn;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
}
int check( int x ) {
int ans = 0;
for( int i = 1;i * i <= x;i ++ )
ans += x / ( i * i ) * mu[i];
return ans;
}
signed main() {
init();
scanf( "%lld", &T );
while( T -- ) {
scanf( "%lld", &k );
int l = 1, r = ( k << 1 );
while( l <= r ) {
int mid = ( l + r ) >> 1;
if( check( mid ) >= k ) r = mid - 1;
else l = mid + 1;
}
if( check( l ) == k ) printf( "%lld\n", l );
else printf( "%lld\n", r );
}
return 0;
}
[HAOI2011]Problemb
- solution
将
a
≤
x
≤
b
,
c
≤
y
≤
d
a\le x\le b,c\le y\le d
a≤x≤b,c≤y≤d二维差分成四个询问
每次询问
1
≤
x
≤
n
,
1
≤
y
≤
m
1\le x\le n,1\le y\le m
1≤x≤n,1≤y≤m的
g
c
d
(
x
,
y
)
=
k
gcd(x,y)=k
gcd(x,y)=k的数对数量
然后再转化为
1
≤
x
≤
n
k
,
1
≤
y
≤
m
k
1\le x\le \frac{n}{k},1\le y\le \frac{m}{k}
1≤x≤kn,1≤y≤km内的互质的数对数量
定义
f
(
i
)
:
g
c
d
(
x
,
y
)
=
i
f(i):gcd(x,y)=i
f(i):gcd(x,y)=i的数对数量,
F
(
i
)
:
i
∣
g
c
d
(
x
,
y
)
F(i):i|gcd(x,y)
F(i):i∣gcd(x,y)的数对数数量
(
1
≤
x
≤
n
,
1
≤
y
≤
m
)
(1\le x\le n,1\le y\le m)
(1≤x≤n,1≤y≤m)
⇒
F
(
i
)
=
⌊
n
i
⌋
⌊
m
i
⌋
⇒
f
(
i
)
=
∑
i
∣
d
μ
(
d
i
)
F
(
i
)
=
∑
i
∣
d
μ
(
d
i
)
⌊
n
i
⌋
⌊
m
i
⌋
\Rightarrow F(i)=\lfloor{\frac{n}{i}}\rfloor\lfloor{\frac{m}{i}}\rfloor\Rightarrow f(i)=\sum_{i|d}\mu(\frac{d}{i})F(i)=\sum_{i|d}\mu(\frac{d}{i})\lfloor{\frac{n}{i}}\rfloor\lfloor{\frac{m}{i}}\rfloor
⇒F(i)=⌊in⌋⌊im⌋⇒f(i)=i∣d∑μ(id)F(i)=i∣d∑μ(id)⌊in⌋⌊im⌋
🧀
⌊
n
i
⌋
⌊
m
i
⌋
\lfloor{\frac{n}{i}}\rfloor\lfloor{\frac{m}{i}}\rfloor
⌊in⌋⌊im⌋其实是一段一段的区间,最多
2
(
n
+
m
)
2(\sqrt{n}+\sqrt{m})
2(n+m)个,从这里入手枚举
那么就需要对前面的
∑
i
∣
d
μ
(
d
i
)
\sum_{i|d}\mu(\frac{d}{i})
∑i∣dμ(id)前缀和
- code
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define maxn 50005
int n, a, b, c, d, k, cnt;
bool vis[maxn];
int prime[maxn], mu[maxn], pre[maxn];
void init() {
mu[1] = 1;
for( int i = 2;i < maxn;i ++ ) {
if( ! vis[i] ) prime[++ cnt] = i, mu[i] = -1;
for( int j = 1;j <= cnt && i * prime[j] < maxn;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for( int i = 1;i < maxn;i ++ ) pre[i] = pre[i - 1] + mu[i];
}
int calc( int n, int m ) {
if( n > m ) swap( n, m );
int last, ans = 0;
for( int i = 1;i <= n;i = last + 1 ) {
last = min( n / ( n / i ), m / ( m / i ) );
ans += ( pre[last] - pre[i - 1] ) * ( n / i ) * ( m / i );
}
return ans;
}
signed main() {
init();
scanf( "%lld", &n );
for( int i = 1, a, b, c, d, k;i <= n;i ++ ) {
scanf( "%lld %lld %lld %lld %lld", &a, &b, &c, &d, &k );
a --, c --;
a /= k, b /= k, c /= k, d /= k;
printf( "%lld\n", calc( b, d ) - calc( a, d ) - calc( b, c ) + calc( a, c ) );
}
return 0;
}
YY的GCD
- solution
既然要求
g
c
d
(
x
,
y
)
gcd(x,y)
gcd(x,y)为质数,而且发现这道题跟上一道problem b很像
先枚举质数,剩下的不就是求
1
≤
x
≤
n
,
1
≤
y
≤
m
,
g
c
d
(
n
,
m
)
=
1
1\le x\le n,1\le y\le m,gcd(n,m)=1
1≤x≤n,1≤y≤m,gcd(n,m)=1的数对数量??
定义
f
(
i
)
:
g
c
d
(
x
,
y
)
=
i
f(i):gcd(x,y)=i
f(i):gcd(x,y)=i的数对数量,
F
(
i
)
:
i
∣
g
c
d
(
x
,
y
)
F(i):i|gcd(x,y)
F(i):i∣gcd(x,y)的数对数数量
(
1
≤
x
≤
n
,
1
≤
y
≤
m
)
(1\le x\le n,1\le y\le m)
(1≤x≤n,1≤y≤m)
F
(
i
)
=
⌊
n
i
⌋
⌊
m
i
⌋
⇒
f
(
i
)
=
∑
i
∣
d
μ
(
d
i
)
F
(
d
)
=
∑
i
∣
d
μ
(
d
i
)
⌊
n
d
⌋
⌊
m
d
⌋
F(i)=\lfloor{\frac{n}{i}}\rfloor\lfloor{\frac{m}{i}}\rfloor\Rightarrow f(i)=\sum_{i|d}\mu(\frac{d}{i})F(d)=\sum_{i|d}\mu(\frac{d}{i})\lfloor{\frac{n}{d}}\rfloor\lfloor{\frac{m}{d}}\rfloor
F(i)=⌊in⌋⌊im⌋⇒f(i)=i∣d∑μ(id)F(d)=i∣d∑μ(id)⌊dn⌋⌊dm⌋🚨
g
c
d
(
x
,
y
)
=
i
gcd(x,y)=i
gcd(x,y)=i的质数已经提出来枚举了
⇒
a
n
s
=
∑
p
m
i
n
(
n
,
m
)
f
(
1
)
=
∑
p
m
i
n
(
n
,
m
)
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
⌊
n
d
×
p
⌋
⌊
m
d
×
p
⌋
\Rightarrow ans=\sum_{p}^{min(n,m)}f(1)=\sum_{p}^{min(n,m)}\sum_{d=1}^{min(n,m)}\mu(d)\lfloor{\frac{n}{d\times p}}\rfloor\lfloor{\frac{m}{d\times p}}\rfloor
⇒ans=p∑min(n,m)f(1)=p∑min(n,m)d=1∑min(n,m)μ(d)⌊d×pn⌋⌊d×pm⌋
如果止步于此,获得的只有美丽的黑色
令
k
=
d
×
p
k=d\times p
k=d×p,则
p
=
k
/
d
p=k/d
p=k/d
⇒
a
n
s
=
∑
k
m
i
n
(
n
,
m
)
⌊
n
k
⌋
⌊
m
k
⌋
∑
p
∣
k
μ
(
k
p
)
\Rightarrow ans=\sum_{k}^{min(n,m)}\lfloor{\frac{n}{k}}\rfloor\lfloor{\frac{m}{k}}\rfloor\sum_{p|k}\mu(\frac{k}{p})
⇒ans=k∑min(n,m)⌊kn⌋⌊km⌋p∣k∑μ(pk)
最后就只剩下对
∑
p
∣
k
μ
(
k
p
)
\sum_{p|k}\mu(\frac{k}{p})
∑p∣kμ(pk)进行前缀和的处理
这里的处理略微不同于上一道题
可以通过暴力枚举质因子,对质因子的倍数进行
μ
\mu
μ的累加,再前缀和处理出来
- code
遇得到哦🙄
define int long long让我直接慢了1s多,导致 T T T了,只能老老实实改long long才能顺利 A C AC AC
#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 10000005
int T, cnt;
int sum[maxn], mu[maxn], prime[maxn];
long long pre[maxn];
bool vis[maxn];
void init( int n ) {
mu[1] = 1;
for( int i = 2;i <= n;i ++ ) {
if( ! vis[i] ) prime[++ cnt] = i, mu[i] = -1;
for( int j = 1;j <= cnt && i * prime[j] < maxn;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for( int j = 1;j <= cnt;j ++ )
for( int i = 1;i * prime[j] <= n;i ++ )
sum[prime[j] * i] += mu[i];
for( int i = 1;i < maxn;i ++ ) pre[i] = pre[i - 1] + sum[i];
}
int main() {
init( 1e7 );
scanf( "%d", &T );
int n, m, r;
long long ans;
while( T -- ) {
scanf( "%d %d", &n, &m );
if( n > m ) swap( n, m );
ans = 0;
for( int i = 1;i <= n;i = r + 1 ) {
r = min( n / ( n / i ), m / ( m / i ) );
ans += 1ll * ( pre[r] - pre[i - 1] ) * ( n / i ) * ( m / i );
}
printf( "%lld\n", ans );
}
return 0;
}
[SDOI2014]数表
- solution
一句话题意,令
s
u
m
(
i
)
sum(i)
sum(i)表示
i
i
i的因子和,给定
n
,
m
,
a
n,m,a
n,m,a,求🍔
∑
1
≤
i
≤
n
,
1
≤
j
≤
m
s
u
m
(
g
c
d
(
i
,
j
)
)
≤
a
s
u
m
(
g
c
d
(
i
,
j
)
)
\sum_{1\le i\le n,1\le j\le m}^{sum(gcd(i,j))\le a}sum(gcd(i,j))
1≤i≤n,1≤j≤m∑sum(gcd(i,j))≤asum(gcd(i,j))
先思考此题的弱化版,即不考虑
a
a
a
∑
i
=
1
n
∑
j
=
1
m
s
u
m
(
g
c
d
(
i
,
j
)
)
\sum_{i=1}^n\sum_{j=1}^msum(gcd(i,j))
i=1∑nj=1∑msum(gcd(i,j))
令
F
(
i
)
F(i)
F(i)表示
1
≤
x
≤
n
,
1
≤
y
≤
m
,
i
∣
g
c
d
(
x
,
y
)
1\le x\le n, 1\le y\le m,i|gcd(x,y)
1≤x≤n,1≤y≤m,i∣gcd(x,y)的数对个数
令
f
(
i
)
f(i)
f(i)表示
1
≤
x
≤
n
,
1
≤
y
≤
m
,
g
c
d
(
x
,
y
)
=
i
1\le x\le n,1\le y\le m,gcd(x,y)=i
1≤x≤n,1≤y≤m,gcd(x,y)=i的数对个数
则有
F
(
i
)
=
∑
i
∣
d
f
(
d
)
,
F
(
i
)
=
⌊
n
i
⌋
⌊
m
i
⌋
F(i)=\sum_{i|d}f(d),F(i)=\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{i}\rfloor
F(i)=i∣d∑f(d),F(i)=⌊in⌋⌊im⌋
莫比乌斯反演
f
(
i
)
=
∑
i
∣
d
μ
(
d
i
)
F
(
d
)
=
∑
i
∣
d
μ
(
d
i
)
⌊
n
d
⌋
⌊
m
d
⌋
f(i)=\sum_{i|d}\mu(\frac{d}{i})F(d)=\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor
f(i)=i∣d∑μ(id)F(d)=i∣d∑μ(id)⌊dn⌋⌊dm⌋
于是,有
a
n
s
=
∑
i
=
1
m
i
n
(
n
,
m
)
s
u
m
(
i
)
f
(
i
)
ans=\sum_{i=1}^{min(n,m)}sum(i)f(i)
ans=i=1∑min(n,m)sum(i)f(i)
=
∑
i
=
1
m
i
n
(
n
,
m
)
s
u
m
(
i
)
∑
i
∣
d
μ
(
d
i
)
⌊
n
d
⌋
⌊
m
d
⌋
=\sum_{i=1}^{min(n,m)}sum(i)\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor
=i=1∑min(n,m)sum(i)i∣d∑μ(id)⌊dn⌋⌊dm⌋
=
∑
d
=
1
m
i
n
(
n
,
m
)
⌊
n
d
⌋
⌊
m
d
⌋
∑
i
∣
d
s
u
m
(
i
)
μ
(
d
i
)
=\sum_{d=1}^{min(n,m)}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\sum_{i|d}sum(i)\mu(\frac{d}{i})
=d=1∑min(n,m)⌊dn⌋⌊dm⌋i∣d∑sum(i)μ(id)
如果现在知道
∑
i
∣
d
s
u
m
(
i
)
μ
(
d
i
)
\sum_{i|d}sum(i)\mu(\frac{d}{i})
∑i∣dsum(i)μ(id),就可以
O
(
s
q
r
t
n
)
O(sqrt{n})
O(sqrtn)的计算出答案
s
u
m
(
i
)
sum(i)
sum(i)可以线性筛得到,与上一题类似,枚举
i
i
i暴力更新倍数,前缀和即可,
O
(
l
o
g
n
)
O(logn)
O(logn)
现在加上限制
a
a
a,又怎么做呢??
其实只有
s
u
m
(
i
)
≤
a
sum(i)\le a
sum(i)≤a的
i
i
i才会产生贡献
自然而然的想到,将
a
,
s
u
m
(
i
)
a,sum(i)
a,sum(i)分别排序,树状数组维护
本质就是树状数组在线插入
至于取模的问题,采取自然溢出的方式即可,具体细节可参见代码
- code
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 100000
#define int long long
struct node {
int n, m, a, id;
}q[maxn], s[maxn];
int prime[maxn], mu[maxn + 5], sum[maxn + 5], tree[maxn + 5], result[maxn + 5];
bool vis[maxn + 5];
int cnt;
bool cmp( node x, node y ) {
return x.a < y.a;
}
void init() {
mu[1] = 1;
for( int i = 2;i <= maxn;i ++ ) {
if( ! vis[i] ) prime[++ cnt] = i, mu[i] = -1;
for( int j = 1;j <= cnt && i * prime[j] <= maxn;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for( int i = 1;i <= maxn;i ++ )
for( int j = i;j <= maxn;j += i ) sum[j] += i;
for( int i = 1;i <= maxn;i ++ )
s[i].a = sum[i], s[i].id = i;
sort( s + 1, s + maxn + 1, cmp );
}
int lowbit( int x ) {
return x & ( -x );
}
void add( int x, int v ) {
for( int i = x;i < maxn;i += lowbit( i ) )
tree[i] += v;
}
int query( int x ) {
int ans = 0;
for( int i = x;i;i -= lowbit( i ) )
ans += tree[i];
return ans;
}
int solve( int n, int m ) {
if( n > m ) swap( n, m );
int ans = 0, r;
for( int i = 1;i <= n;i = r + 1 ) {
r = min( n / ( n / i ), m / ( m / i ) );
ans += ( n / i ) * ( m / i ) * ( query( r ) - query( i - 1 ) );
}
return ans;
}
void Add( int id ) {
for( int i = 1;i * id <= maxn;i ++ )
add( i * id, mu[i] * sum[id] );
}
signed main() {
int Q;
scanf( "%lld", &Q );
for( int i = 1;i <= Q;i ++ )
scanf( "%lld %lld %lld", &q[i].n, &q[i].m, &q[i].a ), q[i].id = i;
sort( q + 1, q + Q + 1, cmp );
init();
int now = 0;
for( int i = 1;i <= Q;i ++ ) {
while( s[now + 1].a <= q[i].a && now < maxn ) Add( s[++ now].id );
result[q[i].id] = solve( q[i].n, q[i].m );
}
int mod = 1ll << 31;
for( int i = 1;i <= Q;i ++ )
printf( "%lld\n", result[i] % mod );
return 0;
}
[国家集训队]Crash的数字表格/JZPTAB
- solution
一句话题意,求🍔 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) \sum_{i=1}^n\sum_{j=1}^mlcm(i,j) i=1∑nj=1∑mlcm(i,j) - s t e p 1 : step1: step1: 枚举最大公因数
= ∑ d = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m i × j d =\sum_{d=1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\frac{i\times j}{d} =d=1∑min(n,m)i=1∑nj=1∑mdi×j
- s t e p 2 : step2: step2: 将最大公因数提到前面,循环上界压缩
= ∑ d = 1 m i n ( n , m ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i × d × j × d d = ∑ d = 1 m i n ( n , m ) d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i × j [ g c d ( i , j ) = 1 ] =\sum_{d=1}^{min(n,m)}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\frac{i\times d\times j\times d}{d}=\sum_{d=1}^{min(n,m)}d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}i\times j\ \ \ \ \ \ \ \ \ \ [gcd(i,j)=1] =d=1∑min(n,m)i=1∑⌊dn⌋j=1∑⌊dm⌋di×d×j×d=d=1∑min(n,m)di=1∑⌊dn⌋j=1∑⌊dm⌋i×j [gcd(i,j)=1]
- s t e p 3 : step3: step3: 利用 ∑ i ∣ n μ ( i ) = [ n = 1 ] \sum_{i|n}\mu(i)=[n=1] ∑i∣nμ(i)=[n=1],对原式不会造成改变
= ∑ d = 1 m i n ( n , m ) d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ∑ k ∣ g c d ( i , j ) μ ( k ) × i × j =\sum_{d=1}^{min(n,m)}d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{k|gcd(i,j)}\mu(k)\times i\times j =d=1∑min(n,m)di=1∑⌊dn⌋j=1∑⌊dm⌋k∣gcd(i,j)∑μ(k)×i×j
- s t e p 4 : step4: step4: 也将 μ \mu μ提到前面,那么为了保证 k ∣ i , k ∣ j k|i,k|j k∣i,k∣j,枚举 i , j i,j i,j变为直接枚举 k i , k j ki,kj ki,kj
= ∑ d = 1 m i n ( n , m ) d ∑ k m i n ( ⌊ n d ⌋ , ⌊ m d ⌋ ) ∑ k i ⌊ n d ⌋ ∑ k j ⌊ m d ⌋ μ ( k ) × k 2 × i × j =\sum_{d=1}^{min(n,m)}d\sum_{k}^{min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)}\sum_{ki}^{\lfloor\frac{n}{d}\rfloor}\sum_{kj}^{\lfloor\frac{m}{d}\rfloor}\mu(k)\times k^2\times i\times j =d=1∑min(n,m)dk∑min(⌊dn⌋,⌊dm⌋)ki∑⌊dn⌋kj∑⌊dm⌋μ(k)×k2×i×j
- s t e p 5 : step5: step5: 将 k k k提出来
=
∑
d
=
1
m
i
n
(
n
,
m
)
d
∑
k
m
i
n
(
⌊
n
d
⌋
,
⌊
m
d
⌋
)
μ
(
k
)
×
k
2
∑
i
=
1
⌊
n
d
×
k
⌋
∑
j
=
1
⌊
m
d
×
k
⌋
i
×
j
=\sum_{d=1}^{min(n,m)}d\sum_{k}^{min(\lfloor\frac{n}{d}\rfloor, \lfloor\frac{m}{d}\rfloor)}\mu(k)\times k^2\sum_{i=1}^{\lfloor\frac{n}{d\times k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d\times k}\rfloor}i\times j
=d=1∑min(n,m)dk∑min(⌊dn⌋,⌊dm⌋)μ(k)×k2i=1∑⌊d×kn⌋j=1∑⌊d×km⌋i×j
⚡:
①
∑
k
m
i
n
(
⌊
n
d
⌋
,
⌊
m
d
⌋
)
μ
(
k
)
×
k
2
\sum_{k}^{min(\lfloor\frac{n}{d}\rfloor, \lfloor\frac{m}{d}\rfloor)}\mu(k)\times k^2
∑kmin(⌊dn⌋,⌊dm⌋)μ(k)×k2使用老套路前缀和优化,之后
O
(
1
)
O(1)
O(1)查询
②
∑
i
=
1
⌊
n
d
×
k
⌋
∑
j
=
1
⌊
m
d
×
k
⌋
i
×
j
\sum_{i=1}^{\lfloor\frac{n}{d\times k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d\times k}\rfloor}i\times j
∑i=1⌊d×kn⌋∑j=1⌊d×km⌋i×j其实就是一个等差数列求积
∑ i = 1 n ∑ j = 1 m i × j = n × ( n + 1 ) 2 . m × ( m + 1 ) 2 \sum_{i=1}^n\sum_{j=1}^mi\times j=\frac{n\times (n+1)}{2}. \frac{m\times (m+1)}{2} i=1∑nj=1∑mi×j=2n×(n+1).2m×(m+1)
- code
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define mod 20101009
#define maxn 10000005
int mu[maxn], prime[maxn], sum[maxn];
bool vis[maxn];
int cnt, inv;
void init() {
mu[1] = 1;
for( int i = 2;i < maxn;i ++ ) {
if( ! vis[i] ) prime[++ cnt] = i, mu[i] = -1;
for( int j = 1;j <= cnt && i * prime[j] < maxn;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for( int i = 1;i < maxn;i ++ )
sum[i] = ( sum[i - 1] + i % mod * i % mod * mu[i] % mod + mod ) % mod;
}
int seq( int n ) {
return n % mod * ( n + 1 ) % mod * inv % mod;
}
int calc( int n, int m ) {
if( n > m ) swap( n, m );
int ans = 0, r;
for( int i = 1;i <= n;i = r + 1 ) {
r = min( n / ( n / i ), m / ( m / i ) );
ans = ( ans + ( sum[r] - sum[i - 1] + mod ) % mod * seq( n / i ) % mod * seq( m / i ) % mod ) % mod;
}
return ans;
}
int qkpow( int x, int y ) {
int ans = 1;
while( y ) {
if( y & 1 ) ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
signed main() {
init();
inv = qkpow( 2, mod - 2 );
int n, m;
scanf( "%lld %lld", &n, &m );
int ans = 0;
for( int d = 1;d <= min( n, m );d ++ )
ans = ( ans + d * calc( n / d, m / d ) % mod ) % mod;
printf( "%lld\n", ans );
return 0;
}
[SDOI2015]约数个数和
- solution
一句话题意,设 d ( x ) d(x) d(x)表示 x x x的约数和,求🍔
∑ i = 1 n ∑ j = 1 m d ( i × j ) \sum_{i=1}^n\sum_{j=1}^md(i\times j) i=1∑nj=1∑md(i×j)
首先有一个约数和的公式🍔
我不是很会证
d ( i × j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] d(i\times j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1] d(i×j)=x∣i∑y∣j∑[gcd(x,y)=1]
=
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
y
)
=
1
]
=\sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]
=i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]
转换一下枚举方式,考虑直接枚举因子
=
∑
i
=
1
n
∑
j
=
1
m
⌊
n
i
⌋
⌊
m
j
⌋
(
g
c
d
(
i
,
j
)
=
1
)
=\sum_{i=1}^n\sum_{j=1}^m\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{j}\rfloor\ \ (gcd(i,j)=1)
=i=1∑nj=1∑m⌊in⌋⌊jm⌋ (gcd(i,j)=1)
设
F
(
i
)
F(i)
F(i)表示
1
≤
x
≤
n
,
1
≤
y
≤
m
,
i
∣
g
c
d
(
x
,
y
)
1\le x\le n,1\le y\le m,i|gcd(x,y)
1≤x≤n,1≤y≤m,i∣gcd(x,y)的约数和
设
f
(
i
)
f(i)
f(i)表示
1
≤
x
≤
n
,
1
≤
y
≤
m
,
i
=
g
c
d
(
x
,
y
)
1\le x\le n,1\le y\le m,i=gcd(x,y)
1≤x≤n,1≤y≤m,i=gcd(x,y)的约数和,
f
(
1
)
f(1)
f(1)即为最终答案
F
(
p
)
=
∑
p
∣
d
f
(
d
)
,
F
(
p
)
=
∑
i
=
1
⌊
n
p
⌋
∑
j
=
1
⌊
m
p
⌋
⌊
n
i
∗
p
⌋
⌊
m
j
∗
p
⌋
F(p)=\sum_{p|d}f(d),F(p)=\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}\lfloor\frac{n}{i*p}\rfloor\lfloor\frac{m}{j*p}\rfloor
F(p)=p∣d∑f(d),F(p)=i=1∑⌊pn⌋j=1∑⌊pm⌋⌊i∗pn⌋⌊j∗pm⌋
莫比乌斯反演
f
(
p
)
=
∑
p
∣
t
μ
(
t
p
)
F
(
t
)
=
∑
p
∣
t
μ
(
t
p
)
∑
i
=
1
⌊
n
t
⌋
∑
j
=
1
⌊
m
t
⌋
⌊
n
i
∗
t
⌋
⌊
m
j
∗
t
⌋
f(p)=\sum_{p|t}\mu(\frac{t}{p})F(t)=\sum_{p|t}\mu(\frac{t}{p})\sum_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{t}\rfloor}\lfloor\frac{n}{i*t}\rfloor\lfloor\frac{m}{j*t}\rfloor
f(p)=p∣t∑μ(pt)F(t)=p∣t∑μ(pt)i=1∑⌊tn⌋j=1∑⌊tm⌋⌊i∗tn⌋⌊j∗tm⌋
最后想求的答案就是
f
(
1
)
f(1)
f(1)
=
∑
t
=
1
m
i
n
(
n
,
m
)
μ
(
t
)
F
(
t
)
,
F
(
t
)
=
∑
i
=
1
⌊
n
t
⌋
∑
j
=
1
⌊
m
t
⌋
⌊
n
i
t
⌋
⌊
m
j
t
⌋
=\sum_{t=1}^{min(n,m)}\mu(t)F(t),F(t)=\sum_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{t}\rfloor}\lfloor\frac{n}{it}\rfloor\lfloor\frac{m}{jt}\rfloor
=t=1∑min(n,m)μ(t)F(t),F(t)=i=1∑⌊tn⌋j=1∑⌊tm⌋⌊itn⌋⌊jtm⌋
对于求 F ( t ) F(t) F(t)的方法,先计算出 S ( t ) = ∑ i = 1 t ⌊ t i ⌋ S(t)=\sum_{i=1}^t\lfloor\frac{t}{i}\rfloor S(t)=∑i=1t⌊it⌋,则可以 O ( 1 ) O(1) O(1)得到
- code
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define maxn 50005
int T, n, m, cnt;
int mu[maxn], prime[maxn], sum[maxn];
bool vis[maxn];
void init() {
mu[1] = 1;
for( int i = 2;i < maxn;i ++ ) {
if( ! vis[i] ) prime[++ cnt] = i, mu[i] = -1;
for( int j = 1;j <= cnt && i * prime[j] < maxn;j ++ ) {
vis[i * prime[j]] = 1;
if( i % prime[j] == 0 ) {
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for( int i = 1;i < maxn;i ++ ) mu[i] += mu[i - 1];
for( int x = 1;x < maxn;x ++ ) {
int ans = 0;
for( int i = 1, j;i <= x;i = j + 1 ) {
j = x / ( x / i );
ans += ( j - i + 1 ) * ( x / i );
}
sum[x] = ans;
}
}
int calc( int n, int m ) {
if( n > m ) swap( n, m );
int ans = 0, r;
for( int i = 1;i <= n;i = r + 1 ) {
r = min( n / ( n / i ), m / ( m / i ) );
ans += ( mu[r] - mu[i - 1] ) * sum[n / i] * sum[m / i];
}
return ans;
}
signed main() {
init();
scanf( "%lld", &T );
while( T -- ) {
scanf( "%lld %lld", &n, &m );
printf( "%lld\n", calc( n, m ) );
}
return 0;
}