文章目录
注意: 由于博主不会使用 L a T e X LaTeX LaTeX,所以决定用 u u u表示莫比乌斯函数。
Part 0 前置芝士
下面的两个不会请左转查询,否则本文完全看不懂
- ∑ \sum ∑的定义与用法
- 等差数列公式
下面的两个东西建议自学,用来做题,不用来推理
3. 整除分块
4. 积性函数欧拉筛
下面的两个东西在难题中往往需要用到,如果不会没关系
5. 杜教筛 (这个博主也不会,可以看出他有多菜)
6. 欧拉函数
ϕ
\phi
ϕ
Part 1 莫比乌斯反演入门
为了方便叙述,设函数 f n = Σ k ∣ n g k f_n=Σ_{k|n} g_k fn=Σk∣ngk。显然,给定 g g g数组可以得出 f f f数组,那么给定 f f f数组能否得到 g g g数组呢?
我们考虑手算来找规律。
①
g
1
=
f
1
g_1=f_1
g1=f1
②
g
2
=
f
2
−
f
1
g_2=f_2-f_1
g2=f2−f1
③
g
3
=
f
3
−
f
1
g_3=f_3-f_1
g3=f3−f1 、
④
g
4
=
f
4
−
f
2
g_4=f_4-f_2
g4=f4−f2
⑤
g
5
=
f
5
−
f
1
g_5=f_5-f_1
g5=f5−f1
⑥
g
6
=
f
6
−
f
3
−
f
2
+
f
1
g_6=f_6-f_3-f_2+f_1
g6=f6−f3−f2+f1
⑦
g
7
=
f
7
−
f
1
g_7=f_7-f_1
g7=f7−f1
⑧
g
8
=
f
8
−
f
4
g_8=f_8-f_4
g8=f8−f4
⑨
g
9
=
f
9
−
f
3
g_9=f_9-f_3
g9=f9−f3
⑩
g
10
=
f
10
−
f
5
−
f
2
+
f
1
g_{10}=f_{10}-f_5-f_2+f_1
g10=f10−f5−f2+f1
容易发现: g n = ∑ k ∣ n u ( n k ) f ( k ) g_n=\sum_{k|n}u(\frac n k)f(k) gn=∑k∣nu(kn)f(k)
其中, μ ( x ) \mu(x) μ(x)仅仅与 x x x的值有关。注意 μ ( x ) \mu(x) μ(x)的值为 0 0 0, 1 1 1或 − 1 -1 −1。
然后,我们通过公式,写下 μ ( 1 ) , μ ( 2 ) … … μ ( 10 ) \mu(1),\mu(2)……\mu(10) μ(1),μ(2)……μ(10)的值。
μ
(
1
)
=
1
\mu(1)=1
μ(1)=1
μ
(
2
)
=
−
1
\mu(2)=-1
μ(2)=−1
μ
(
3
)
=
−
1
\mu(3)=-1
μ(3)=−1
μ
(
4
)
=
0
\mu(4)=0
μ(4)=0
μ
(
5
)
=
−
1
\mu(5)=-1
μ(5)=−1
μ
(
6
)
=
1
\mu(6)=1
μ(6)=1
μ
(
7
)
=
−
1
\mu(7)=-1
μ(7)=−1
μ
(
8
)
=
0
\mu(8)=0
μ(8)=0
μ
(
9
)
=
0
\mu(9)=0
μ(9)=0
μ
(
10
)
=
1
\mu(10)=1
μ(10)=1
……
接着我们得到了
M
o
b
i
u
s
Mobius
Mobius函数的规律。
质因子分解得 n = ∏ i = 1 m p i c i n=∏_{i=1}^m p_i^{c_i} n=∏i=1mpici,其中 p i ( 1 ≤ i ≤ m ) p_i(1≤i≤m) pi(1≤i≤m)均为质数。
①当存在
c
i
(
1
≤
i
≤
m
)
>
1
c_i(1≤i≤m)>1
ci(1≤i≤m)>1时,
μ
(
n
)
=
0
\mu(n)=0
μ(n)=0;
②当
m
m
m为奇数时,
μ
(
n
)
=
−
1
\mu(n)=-1
μ(n)=−1;
③当
m
m
m为偶数时,
μ
(
n
)
=
1
\mu(n)=1
μ(n)=1。
Part 2 莫比乌斯函数筛
我们希望能够快速得到 μ ( n ) \mu(n) μ(n)的值。如果是单次询问,那么我们可以在 O ( n ) O(\sqrt n) O(n)代价下将 n n n进行质因数分解并求得 m m m(质因子分解得 n = ∏ i = 1 m p i c i n=∏_{i=1}^m p_i^{c_i} n=∏i=1mpici),然后判断 m m m是否为 1 1 1以及其奇偶性即可。
但是,往往莫比乌斯反演题需要许多数的莫比乌斯函数值,所以我们需要一种筛法来快速得到 1 − n 1-n 1−n的莫比乌斯函数值。
直接上代码,里面有注释:
#define rg register
int m[100005];//m_i就是u(i)的值,即记录莫比乌斯值的数组
bool v[100005]={0};//如果i为质数,那么v_i=1;否则v_i=0
for (rg int i=1;i<=n;i++) v[i]=1,m[i]=1;//重要的预处理
for (rg int i=2;i<=n;++i)
{
if (v[i]==0) continue;//如果它是合数,就不用它筛
m[i]=-1;//留下来的是质数,即质因子个数为1,则u(i)=-1
for (rg int j=2*i;j<=n;j+=i)//开始筛,找i的倍数
{
v[j]=0;//被筛掉了,j是合数
if ((j/i)%i==0) m[j]=0;//如果它含有多个质因子i,那么显然u(j)=0
else m[j]=m[j]*(-1);//积性函数巧用
}
}
时间复杂度为 O ( n ) O(n) O(n),在一般情况下不会超时。
Part 3 莫比乌斯函数性质与证明
Part 3.1 莫比乌斯函数性质
性质
1
1
1: 若
f
(
k
)
=
∑
d
∣
k
g
(
d
)
f(k)=\sum_{d|k} g(d)
f(k)=∑d∣kg(d),则
g
(
k
)
=
∑
d
∣
k
μ
(
k
d
)
f
(
d
)
=
∑
d
∣
k
μ
(
d
)
f
(
k
d
)
g(k)=\sum_{d|k}\ \mu(\frac k d) f(d)=\sum_{d|k}\ \mu(d) f(\frac k d)
g(k)=∑d∣k μ(dk)f(d)=∑d∣k μ(d)f(dk)
性质 2 2 2: 莫比乌斯函数为积性函数。即若 n ⊥ m n⊥m n⊥m,那么有 μ ( n ) μ ( m ) = μ ( n m ) \mu(n)\mu(m)=\mu(nm) μ(n)μ(m)=μ(nm)。
性质 3 3 3: ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum_{d|n} \mu(d)=[n=1] ∑d∣nμ(d)=[n=1]。
性质 4 4 4: f ( i j ) = ∑ a ∣ i ∑ b ∣ i [ g c d ( a , b ) = 1 ] f(ij)=\sum_{a|i} \sum_{b|i} [gcd(a,b)=1] f(ij)=∑a∣i∑b∣i[gcd(a,b)=1],其中 f ( x ) f(x) f(x)表示 x x x的因数个数(请思考其与莫比乌斯函数的关系)。
Part 3.2 莫比乌斯函数性质证明
性质 1 1 1: 莫比乌斯函数的由来,前已证
性质 2 2 2:
显然,若 n n n与 m m m互质,则 n n n的任何一个质因数与 m m m的任何一个质因数完全不同。
我们尝试证明下面六个东西:
①
μ
(
n
)
=
0
\mu(n)=0
μ(n)=0时有
μ
(
m
n
)
=
0
\mu(mn)=0
μ(mn)=0。此时
n
n
n有多个相同的质因数,显然
n
m
nm
nm也有多个相同的质因数,故有
μ
(
n
m
)
=
0
\mu(nm)=0
μ(nm)=0。
②
μ
(
m
)
=
0
\mu(m)=0
μ(m)=0时有
μ
(
m
n
)
=
0
\mu(mn)=0
μ(mn)=0。这种情况与①相同。
③
μ
(
n
)
=
1
,
μ
(
m
)
=
1
\mu(n)=1,\mu(m)=1
μ(n)=1,μ(m)=1时有
μ
(
n
m
)
=
1
\mu(nm)=1
μ(nm)=1。此时
n
n
n与
m
m
m均有偶数个不同的质因数,因为
n
n
n与
m
m
m互质,故
n
m
nm
nm有偶数个不同的质因数,即
μ
(
n
m
)
=
1
\mu(nm)=1
μ(nm)=1。
④
μ
(
n
)
=
1
,
μ
(
m
)
=
−
1
\mu(n)=1,\mu(m)=-1
μ(n)=1,μ(m)=−1时有
μ
(
n
m
)
=
−
1
\mu(nm)=-1
μ(nm)=−1。
⑤
μ
(
n
)
=
−
1
,
μ
(
m
)
=
1
\mu(n)=-1,\mu(m)=1
μ(n)=−1,μ(m)=1时有
μ
(
n
m
)
=
−
1
\mu(nm)=-1
μ(nm)=−1。
⑥
μ
(
n
)
=
−
1
,
μ
(
m
)
=
−
1
\mu(n)=-1,\mu(m)=-1
μ(n)=−1,μ(m)=−1时有
μ
(
n
m
)
=
1
\mu(nm)=1
μ(nm)=1。
注意④⑤⑥的证法与③基本相同,这里不再赘述。
上面①②③④⑤⑥涵盖了所有的情况,均满足要求,故性质 2 2 2成立。
性质
3
3
3:
①若
n
=
1
n=1
n=1,那么显然原式为
1
1
1;
②若
n
≠
1
n≠1
n=1,则在
g
(
k
)
=
∑
d
∣
k
μ
(
k
d
)
f
(
d
)
g(k)=\sum_{d|k}\ \mu(\frac k d) f(d)
g(k)=∑d∣k μ(dk)f(d)中,所有含有因数
1
1
1且被枚举到的
d
d
d的系数之和为
0
0
0。由于所有数都是
1
1
1的倍数,所以可得到
∑
d
∣
n
μ
(
d
)
=
[
n
=
1
]
\sum_{d|n} \mu(d)=[n=1]
∑d∣nμ(d)=[n=1]。
故性质 3 3 3成立。
性质 4 4 4: f ( i j ) = ∑ a ∣ i ∑ b / j [ g c d ( a , b ) = 1 ] f(ij)=\sum_{a|i} \sum_{b/j} [gcd(a,b)=1] f(ij)=∑a∣i∑b/j[gcd(a,b)=1]。
设 a a a, b b b分别为 x , y x,y x,y的不同质因子个数。
证明如下:
设存在质数
p
p
p,
i
=
i
′
×
p
x
1
,
j
=
j
′
×
p
x
2
i=i'×p^{x1},j=j'×p^{x2}
i=i′×px1,j=j′×px2。
显然,
i
j
ij
ij的因数中,含有质因子
p
p
p的个数在
0
0
0至
x
1
+
x
2
x1+x2
x1+x2之间,即含有质因子
p
p
p的个数有
x
1
+
x
2
+
1
x1+x2+1
x1+x2+1种。
考虑右式。同理,设 a = a ′ × p x 3 , b = b ′ × p x 4 a=a'×p^{x3},b=b'×p^{x4} a=a′×px3,b=b′×px4。此时,当 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1时,一定需要 g c d ( a ′ × p x 3 , b ′ × p x 4 ) = 1 gcd(a'×p^{x3},b'×p^{x4})=1 gcd(a′×px3,b′×px4)=1才能满足要求。
观察一下这个式子,可以发现: g c d ( p x 3 , p x 4 ) = 1 gcd(p^{x3},p^{x4})=1 gcd(px3,px4)=1;即, x 3 = 0 x3=0 x3=0或 x 4 = 0 x4=0 x4=0。
分类讨论一下。
①当
x
3
=
0
x3=0
x3=0时,
x
4
x4
x4有
x
2
+
1
x2+1
x2+1种取值(
0
0
0至
x
2
x2
x2);
②当
x
4
=
0
x4=0
x4=0时,同理
x
3
x3
x3有
x
1
+
1
x1+1
x1+1种取值。
③注意此时
x
3
=
x
4
=
0
x3=x4=0
x3=x4=0的情况被重复算了一次,所以还要减去1。
即,右式xy含有质因子 p p p的个数有 ( x 2 + 1 ) + ( x 1 + 1 ) − 1 = x 1 + x 2 + 1 (x2+1)+(x1+1)-1=x1+x2+1 (x2+1)+(x1+1)−1=x1+x2+1种,与左式相同。
故性质 4 4 4成立。
Part 4.1 简单例题分析
T1: [模板]莫比乌斯反演
Description
已知 f ( k ) = ∑ d ∣ k g ( d ) f(k)=\sum_{d|k} g(d) f(k)=∑d∣kg(d),现在给出 f 1 f_1 f1至 f n ( n ≤ 1 0 6 ) f_n(n≤10^6) fn(n≤106)的值,请求出 g 1 g_1 g1至 g n g_n gn的值。
Solution
线性筛求出每个数的莫比乌斯函数值。然后,根据 g ( k ) = ∑ d ∣ k μ ( k d ) f ( d ) g(k)=\sum_{d|k}\ \mu(\frac k d) f(d) g(k)=∑d∣k μ(dk)f(d)即可得到 g 1 , g 2 … g n g_1,g_2…g_n g1,g2…gn。
T2.1: Zap-Queries(Easy Divsion)
Description
给定 n , m , k ( d ≤ n , m ≤ 5 × 1 0 4 ) n,m,k(d≤n,m≤5×10^4) n,m,k(d≤n,m≤5×104),请求出 ∑ i = 1 n ∑ j = 1 m ( gcd ( i , j ) = k ) \sum_{i=1}^n \sum_{j=1}^m (\gcd(i,j)=k) ∑i=1n∑j=1m(gcd(i,j)=k)。
Solution
显然,我们不能以 O ( n 2 l o g 2 n ) O(n^2 log_2n) O(n2log2n)的代价直接暴力。
∑
i
=
1
n
∑
j
=
1
m
(
gcd
(
i
,
j
)
=
k
)
\sum_{i=1}^n \sum_{j=1}^m (\gcd(i,j)=k)
∑i=1n∑j=1m(gcd(i,j)=k)
=
∑
i
=
1
[
n
k
]
∑
j
=
1
[
m
k
]
(
gcd
(
i
,
j
)
=
1
)
=\sum_{i=1}^{[\frac n k]} \sum_{j=1}^{[\frac m k]} (\gcd(i,j)=1)
=∑i=1[kn]∑j=1[km](gcd(i,j)=1)
推到这一步,我们观察一下 ( g c d ( i , j ) = 1 ) (gcd(i,j)=1) (gcd(i,j)=1)这一项,发现是 [ a = 1 ] [a=1] [a=1]这一形式,所以我们可以使用莫比乌斯函数性质3来转换:
= ∑ i = 1 [ n k ] ∑ j = 1 [ m k ] ∑ d ∣ gcd ( i , j ) u ( d ) =\sum_{i=1}^{[\frac n k]} \sum_{j=1}^{[\frac m k]} \sum_{d|\gcd(i,j)} u(d) =∑i=1[kn]∑j=1[km]∑d∣gcd(i,j)u(d)
有什么用呢?我们尝试把 d d d提出来,那么就有
= ∑ d = 1 m i n ( [ n k ] , [ m k ] ) u ( d ) ∑ i = 1 [ n d ] ∑ j = 1 [ m d ] ( d ∣ gcd ( i , j ) ) =\sum_{d=1}^{min({[\frac n k]},{[\frac m k]})} u(d) \sum_{i=1}^{[\frac n {d}]} \sum_{j=1}^{[\frac m {d}]} (d|\gcd(i,j)) =∑d=1min([kn],[km])u(d)∑i=1[dn]∑j=1[dm](d∣gcd(i,j))
小学奥数告诉我们,若 d ∣ i , d ∣ j d|i,d|j d∣i,d∣j则有 d ∣ gcd ( i , j ) d|\gcd(i,j) d∣gcd(i,j)。所以,我们再改写这个式子:
= ∑ d = 1 m i n ( [ n k ] , [ m k ] ) u ( d ) [ n d k ] [ m d k ] =\sum_{d=1}^{min({[\frac n k]},{[\frac m k]})} u(d) [\frac n {dk}] [\frac m {dk}] =∑d=1min([kn],[km])u(d)[dkn][dkm]
模拟这个式子即可,时间复杂度 O ( m i n ( [ n k ] , [ m k ] ) ) O(min({[\frac n k]},{[\frac m k]})) O(min([kn],[km]))。
T2.2: Zap-Queries(Hard Division)
Description
给定 n , m , k ( d ≤ n , m ≤ 5 × 1 0 4 ) n,m,k(d≤n,m≤5×10^4) n,m,k(d≤n,m≤5×104), q ( q ≤ 5 × 1 0 4 ) q(q≤5×10^4) q(q≤5×104)次询问 ∑ i = 1 n ∑ j = 1 m ( gcd ( i , j ) = k ) \sum_{i=1}^n \sum_{j=1}^m (\gcd(i,j)=k) ∑i=1n∑j=1m(gcd(i,j)=k)的值。
Solution
首先,通过 T 2.1 T2.1 T2.1的推导,我们得到了它:
∑ d = 1 m i n ( [ n k ] , [ m k ] ) u ( d ) [ n d k ] [ m d k ] \sum_{d=1}^{min({[\frac n k]},{[\frac m k]})} u(d) [\frac n {dk}] [\frac m {dk}] ∑d=1min([kn],[km])u(d)[dkn][dkm]。
对于多次询问的情况下,时间复杂度变成了 O ( q m i n ( [ n k ] , [ m k ] ) ) O(q\ min({[\frac n k]},{[\frac m k]})) O(q min([kn],[km])),显然会超时。
可以发现,后面的 [ n d k ] [ m d k ] [\frac n {dk}] [\frac m {dk}] [dkn][dkm]是可以通过整除分块优化的。对于每一个块都使得 [ n d k ] [ m d k ] [\frac n {dk}] [\frac m {dk}] [dkn][dkm]的值相同,那么我们就可以提出它,而剩下的就是该块内所有数的莫比乌斯函数值之和(区间和)。所以我们可以在预处理(筛) M o b i u s Mobius Mobius函数的时候记录下前缀和,以后每次区间询问的时间复杂度就是 O ( 1 ) O(1) O(1)啦。
时间复杂度: O ( q m i n ( [ n k ] , [ m k ] ) ) O(q\sqrt {min({[\frac n k]},{[\frac m k]})}) O(qmin([kn],[km])),不会超时。
Code
#include <bits/stdc++.h>
#define n 50000
#define rg register
using namespace std;
static int q,a,b,c;
static long long ans=0;
static int m[100005],pre[100005];
static bool v[100005]={0};
inline int read()
{
int s=0,w=1;
char ch=getchar();
while (ch<'0'||ch>'9')
{
if (ch=='-') w=-w;
ch=getchar();
}
while (ch>='0'&&ch<='9')
{
s=(s<<1)+(s<<3)+(ch^'0');
ch=getchar();
}
return s*w;
}
signed main()
{
cin>>q;
q++;
for (rg int i=1;i<=n;i++) v[i]=1,m[i]=1;
for (rg int i=2;i<=n;++i)
{
if (v[i]==0) continue;
m[i]=-1;
for (rg int j=2*i;j<=n;j+=i)
{
v[j]=0;
if ((j/i)%i==0) m[j]=0;
else m[j]=m[j]*(-1);
}
}
for (rg int i=1;i<=n;++i) pre[i]=pre[i-1]+m[i];
while (--q)
{
a=read(),b=read(),c=read();
a/=c,b/=c,ans=0;
for (rg int l=1,r;l<=min(a,b);l=r+1) r=min(a/(a/l),b/(b/l)),ans+=1ll*(a/l)*(b/l)*(1ll*pre[r]-pre[l-1]);
printf("%lld\n",ans);
}
return 0;
}
注意本题略微卡常,所以注意int与long long中,尽可能地使用int,实在不行再用long long。
T3 公约数的和(Luogu P1390)
Description
求出 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) \sum_{i=1}^n \sum_{j=i+1}^n gcd(i,j) ∑i=1n∑j=i+1ngcd(i,j)。
Solution
首先,我们需要魔改一下题目,把我们要求的改成 ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) \sum_{i=1}^n \sum_{j=1}^n gcd(i,j) ∑i=1n∑j=1ngcd(i,j)①。由于 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) = ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) − n ( n + 1 ) 2 2 \sum_{i=1}^n \sum_{j=i+1}^n gcd(i,j)=\frac {\sum_{i=1}^n \sum_{j=1}^n gcd(i,j)-{\frac {n(n+1)} 2}} 2 ∑i=1n∑j=i+1ngcd(i,j)=2∑i=1n∑j=1ngcd(i,j)−2n(n+1)且后者不会溢出,所以我们只需要求出①就可以啦。
仍然将原式进行转换,如下:
∑
i
=
1
n
∑
j
=
1
n
g
c
d
(
i
,
j
)
\sum_{i=1}^n \sum_{j=1}^n gcd(i,j)
∑i=1n∑j=1ngcd(i,j)
=
∑
k
=
1
n
k
∑
i
=
1
n
∑
j
=
1
n
g
c
d
(
i
,
j
)
=
k
=\sum_{k=1}^n k\sum_{i=1}^n \sum_{j=1}^n gcd(i,j)=k
=∑k=1nk∑i=1n∑j=1ngcd(i,j)=k
可以发现后半段 ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) = k \sum_{i=1}^n \sum_{j=1}^n gcd(i,j)=k ∑i=1n∑j=1ngcd(i,j)=k与T2.2 Zap-Queries的做法相似,即
∑
i
=
1
n
∑
j
=
1
n
g
c
d
(
i
,
j
)
\sum_{i=1}^n \sum_{j=1}^n gcd(i,j)
∑i=1n∑j=1ngcd(i,j)
=
∑
d
=
1
m
i
n
(
[
n
k
]
,
[
m
k
]
)
u
(
d
)
[
n
d
k
]
[
m
d
k
]
=\sum_{d=1}^{min({[\frac n k]},{[\frac m k]})} u(d) [\frac n {dk}] [\frac m {dk}]
=∑d=1min([kn],[km])u(d)[dkn][dkm]
所以原式为 ∑ k = 1 n k ∑ d = 1 [ n k ] u ( d ) [ n k d ] 2 \sum_{k=1}^n k \sum_{d=1}^{[\frac n k]} u(d) [\frac n {kd}]^2 ∑k=1nk∑d=1[kn]u(d)[kdn]2
可以发现,我们可以分块套分块。即以 [ n k ] [\frac n k] [kn]做一次分块,里面的 ∑ d = 1 [ n k ] u ( d ) [ n k d ] 2 \sum_{d=1}^{[\frac n k]} u(d) [\frac n {kd}]^2 ∑d=1[kn]u(d)[kdn]2再做一次分块;注意需要预处理筛出莫比乌斯函数值并使用前缀和来使区间查询的时间复杂度为 O ( 1 ) O(1) O(1)。
综上所述,时间复杂度为 O ( n n ) = O ( n ) O(\sqrt n \sqrt n)=O(n) O(nn)=O(n)。
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxlen=2000000;
int n,ans=0;
int v[maxlen+5],m[maxlen+5],pre[maxlen+5];
inline void init()
{
for (int i=1;i<=maxlen;i++) v[i]=m[i]=1;
for (int i=2;i<=maxlen;i++)
{
if (v[i]==0) continue;
m[i]=-1;
for (int j=2*i;j<=maxlen;j+=i)
{
v[j]=0;
if ((j/i)%i==0) m[j]=0;
else m[j]=m[j]*(-1);
}
}
for (int i=1;i<=maxlen;i++) pre[i]=pre[i-1]+m[i];
}
signed main()
{
cin>>n;
init();
int al,ar;
for (al=1;al<=n;al++)
{
ar=n/(n/al);
int now=n/al,bl,br,res=0;
for (bl=1;bl<=now;bl++)
{
br=now/(now/bl);
res+=(pre[br]-pre[bl-1])*(now/bl)*(now/bl);
bl=br;
}
ans+=res*(((al+ar)*(ar-al+1))/2);
al=ar;
}
ans=ans-((n+1)*n)/2;
cout<<ans/2<<endl;
return 0;
}
T4 约数个数和(Luogu P3327)
Description
给定 n n n, m m m, q q q次询问 ∑ i = 1 n ∑ j = 1 m f ( i j ) \sum_{i=1}^n \sum_{j=1}^m f(ij) ∑i=1n∑j=1mf(ij)的值,其中 f ( x ) f(x) f(x)表示 x x x的约数个数。
Solution
根据莫比乌斯函数的性质 4 4 4,可以得到
∑
i
=
1
n
∑
j
=
1
m
f
(
i
j
)
\sum_{i=1}^n \sum_{j=1}^m f(ij)
∑i=1n∑j=1mf(ij)
=
∑
i
=
1
n
∑
j
=
1
m
∑
a
∣
i
∑
b
∣
j
[
g
c
d
(
a
,
b
)
=
1
]
=\sum_{i=1}^n \sum_{j=1}^m \sum_{a|i} \sum_{b|j} [gcd(a,b)=1]
=∑i=1n∑j=1m∑a∣i∑b∣j[gcd(a,b)=1]
然后通过套路,得到
∑
i
=
1
n
∑
j
=
1
m
∑
a
∣
i
∑
b
∣
j
∑
d
∣
g
c
d
(
a
,
b
)
u
(
d
)
\sum_{i=1}^n \sum_{j=1}^m \sum_{a|i} \sum_{b|j} \sum_{d|gcd(a,b)} u(d)
∑i=1n∑j=1m∑a∣i∑b∣j∑d∣gcd(a,b)u(d)
把 d d d往前提,得到
∑ d = 1 m i n ( n , m ) u ( d ) ∑ a = 1 [ n d ] [ n a d ] ∑ b = 1 [ m d ] [ m b d ] \sum_{d=1}^{min(n,m)} u(d) \sum_{a=1}^{[\frac n d]} [\frac n {ad}] \sum_{b=1}^{[\frac m d]} [\frac m {bd}] ∑d=1min(n,m)u(d)∑a=1[dn][adn]∑b=1[dm][bdm]
此时,我们可以发现,通过分块套分块可以把时间复杂度优化到每次询问 O ( m i n ( n , m ) ) O(min(n,m)) O(min(n,m)),即总时间复杂度为 O ( q m i n ( n , m ) ) O(qmin(n,m)) O(qmin(n,m))。
期望得分70分。
显然,时间复杂度为 O ( q m i n ( n , m ) ) O(qmin(n,m)) O(qmin(n,m))的做法必然会超时,考虑优化。
首先,前面几道题目启发我们预处理(线性筛)莫比乌斯函数,然后处理出前缀和来用。这题我们采用同样的方法,但是要多预处理一个东西,即对于每个 x x x,预处理出 ∑ i = 1 x [ x i ] \sum_{i=1}^x [\frac x i] ∑i=1x[ix]的值,并用数组记录。这一步预处理的时间复杂度为 O ( n n ) O(n \sqrt n) O(nn)。
此时,既然得到了上面的东西,那么我们就优化掉了里面的一个分块,这样每次询问的时间复杂度就是 O ( m i n ( n , m ) ) O(\sqrt {min(n,m)}) O(min(n,m)),则询问的时间复杂度为 O ( q m i n ( n , m ) ) O(q\sqrt {min(n,m)}) O(qmin(n,m))。
综上所述,总时间复杂度为 O ( n n + ( q m i n ( n , m ) ) O(n \sqrt n+(q\sqrt {min(n,m)}) O(nn+(qmin(n,m)),可以通过。
期望得分100分。
Code
#include <bits/stdc++.h>
#define maxlen 100000
using namespace std;
int t,n,m;
int v[100005],pre[100005],num[100005],a[100005];
inline void init()
{
for (int i=1;i<=maxlen;i++) a[i]=v[i]=1;
for (register int i=2;i<=maxlen;++i)
{
if (v[i]==0) continue;
a[i]=-1;
for (register int j=2*i;j<=maxlen;j+=i)
{
v[j]=0;
if ((j/i)%i==0) a[j]=0;
a[j]*=(-1);
}
}
for (int i=1;i<=maxlen;++i) pre[i]=pre[i-1]+a[i];
}
inline void init2()
{
for (register int i=1;i<=maxlen;++i)
{
int tot=0;
for (register int l=1,r;l<=i;++l)
{
r=min(i,i/(i/l));
tot+=(r-l+1)*(i/l);
l=r;
}
num[i]=tot;
}
}
signed main()
{
cin>>t;
init();
init2();
while (t--)
{
cin>>n>>m;
long long ans=0;
for (register int al=1,ar;al<=min(n,m);++al)
{
ar=min(min(n/(n/al),m/(m/al)),n);
ans=1ll*ans+1ll*num[n/al]*num[m/al]*(pre[ar]-pre[al-1]);
al=ar;
}
cout<<ans<<endl;
}
return 0;
}
Part 4.2 综合例题分析
T5 最小公倍数之和
Description
求 ∑ i = 1 n ∑ j = 1 n l c m ( i , j ) \sum_{i=1}^n \sum_{j=1}^n lcm(i,j) ∑i=1n∑j=1nlcm(i,j) 。
Subtasks
Subtask 1(10pts):
n
≤
1
0
3
n≤10^3
n≤103
Subtask 2(50pts):
n
≤
1
0
6
n≤10^6
n≤106
Subtask 3(40pts):
n
≤
1
0
12
n≤10^{12}
n≤1012
Solution
自以为是地推推看:
∑
i
=
1
n
∑
j
=
1
n
l
c
m
(
i
,
j
)
\sum_{i=1}^n \sum_{j=1}^n lcm(i,j)
∑i=1n∑j=1nlcm(i,j)
=
∑
i
=
1
n
∑
j
=
1
n
i
j
g
c
d
(
i
,
j
)
=\sum_{i=1}^n \sum_{j=1}^n \frac {ij} {gcd(i,j)}
=∑i=1n∑j=1ngcd(i,j)ij
=
∑
k
=
1
n
∑
i
=
1
n
∑
j
=
1
n
i
j
k
[
g
c
d
(
i
,
j
)
=
k
]
=\sum_{k=1}^n \sum_{i=1}^n \sum_{j=1}^n \frac {ij} {k} {[gcd(i,j)=k]}
=∑k=1n∑i=1n∑j=1nkij[gcd(i,j)=k]
=
∑
k
=
1
n
k
∑
i
=
1
[
n
k
]
∑
j
=
1
[
n
k
]
i
j
[
g
c
d
(
i
,
j
)
=
1
]
=\sum_{k=1}^n k \sum_{i=1}^{[\frac n k]} \sum_{j=1}^{[\frac n k]} ij {[gcd(i,j)=1]}
=∑k=1nk∑i=1[kn]∑j=1[kn]ij[gcd(i,j)=1]
=
∑
k
=
1
n
k
∑
i
=
1
[
n
k
]
∑
j
=
1
[
n
k
]
i
j
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
=\sum_{k=1}^n k \sum_{i=1}^{[\frac n k]} \sum_{j=1}^{[\frac n k]} ij \sum_{d|gcd(i,j)} \mu(d)
=∑k=1nk∑i=1[kn]∑j=1[kn]ij∑d∣gcd(i,j)μ(d)
=
∑
k
=
1
n
k
∑
d
=
1
[
n
k
]
μ
(
d
)
×
d
2
×
∑
i
=
1
[
n
k
d
]
∑
j
=
1
[
n
k
d
]
i
j
=\sum_{k=1}^n k \sum_{d=1}^{[\frac n k]} \mu(d)×d^2×\sum_{i=1}^{[\frac n {kd}]} \sum_{j=1}^{[\frac n {kd}]} ij
=∑k=1nk∑d=1[kn]μ(d)×d2×∑i=1[kdn]∑j=1[kdn]ij
=
∑
k
=
1
n
k
∑
d
=
1
[
n
k
]
μ
(
d
)
×
d
2
×
g
(
n
k
d
)
2
=\sum_{k=1}^n k \sum_{d=1}^{[\frac n k]} \mu(d)×d^2×g(\frac n {kd})^2
=∑k=1nk∑d=1[kn]μ(d)×d2×g(kdn)2
注意,这里定义函数 g ( x ) g(x) g(x)表示 ∑ i = 1 x i \sum_{i=1}^x i ∑i=1xi的值。
显然,预处理出莫比乌斯函数及其前缀和,且使用整除分块套整除分块可以把时间复杂度优化到 O ( n × n ) = O ( n ) O(\sqrt n×\sqrt n)=O(n) O(n×n)=O(n)。
期望得分 50 50 50分。
观察一下上面这个式子,没有什么可优化的。
真的吗?
为了方便叙述,设 k d = x kd=x kd=x,则
原式 = ∑ k = 1 n k ∑ d = 1 [ n k ] μ ( d ) × d 2 × g ( n k d ) 2 =\sum_{k=1}^n k \sum_{d=1}^{[\frac n k]} \mu(d)×d^2×g(\frac n {kd})^2 =∑k=1nk∑d=1[kn]μ(d)×d2×g(kdn)2
=
∑
x
=
1
n
g
(
[
n
x
]
)
2
∑
k
∣
x
k
μ
(
[
x
k
]
)
×
[
x
k
]
2
=\sum_{x=1}^n g([\frac n x])^2 \sum_{k|x} k\ \mu([\frac x k])×[\frac x k]^2
=∑x=1ng([xn])2∑k∣xk μ([kx])×[kx]2
=
∑
x
=
1
n
g
(
[
n
x
]
)
2
∑
k
∣
x
k
μ
(
k
)
x
=\sum_{x=1}^n g([\frac n x])^2 \sum_{k|x} k\ \mu(k)\ x
=∑x=1ng([xn])2∑k∣xk μ(k) x
=
∑
x
=
1
n
g
(
[
n
x
]
)
2
x
∑
k
∣
x
k
μ
(
k
)
=\sum_{x=1}^n g([\frac n x])^2 x \sum_{k|x} k\ \mu(k)
=∑x=1ng([xn])2x∑k∣xk μ(k)
貌似也没什么用啊……但是后面这个
∑
k
∣
x
k
μ
(
k
)
\sum_{k|x} k\ \mu(k)
∑k∣xk μ(k)看起来蛮可爱的,是不是可以预处理它呢?
设 a , b a,b a,b为互质的两个正整数, f ( k ) = ∑ k ∣ x k μ ( k ) f(k)=\sum_{k|x} k\ \mu(k) f(k)=∑k∣xk μ(k),有 f ( a ) × f ( b ) = f ( a b ) f(a)×f(b)=f(ab) f(a)×f(b)=f(ab)③。故f是一个积性函数。
③成立的原因显然,即 a a a与 b b b互质时, a a a的一个因数乘上 b b b的一个因数恰好填充了所有 a b ab ab的因数,即 a a a对答案的贡献与 b b b的答案的贡献是没有重叠的。
故我们可以用欧拉筛预处理出 f f f的值,然后维护出前缀和之后带入原式,用整除分块即可将时间复杂度优化到 O ( n ) O(\sqrt n) O(n)。