1.一句话定义:
狄利克雷卷积是形如
f
(
x
)
=
g
(
x
)
∗
h
(
x
)
f(x)=g(x)*h(x)
f ( x ) = g ( x ) ∗ h ( x ) 的式子(*是狄利克雷卷积符号,我也不知道手写叉乘行不行 ),它表示的含义为
f
(
x
)
=
∑
d
∣
x
g
(
d
)
×
h
(
x
/
d
)
f(x)=\sum_{d|x} g(d)\times h(x/d)
f ( x ) = ∑ d ∣ x g ( d ) × h ( x / d ) .
2.性质:
狄利克雷卷积满足交换律,结合律。如:
f
(
x
)
∗
g
(
x
)
=
g
(
x
)
∗
h
(
x
)
,
f
(
x
)
∗
g
(
x
)
∗
h
(
x
)
=
f
(
x
)
∗
(
g
(
x
)
∗
h
(
x
)
)
f(x)*g(x)=g(x)*h(x),f(x)*g(x)*h(x)=f(x)*(g(x)*h(x))
f ( x ) ∗ g ( x ) = g ( x ) ∗ h ( x ) , f ( x ) ∗ g ( x ) ∗ h ( x ) = f ( x ) ∗ ( g ( x ) ∗ h ( x ) ) 。
还有一个很强的性质: 若
f
(
x
)
=
∑
d
∣
x
g
(
d
)
×
h
(
x
/
d
)
f(x)=\sum_{d|x}g(d)\times h(x/d)
f ( x ) = ∑ d ∣ x g ( d ) × h ( x / d ) ,
g
,
h
均
为
积
性
函
数
,
则
f
也
是
积
性
函
数
。
g,h均为积性函数,则f也是积性函数。
g , h 均 为 积 性 函 数 , 则 f 也 是 积 性 函 数 。 (我的天啊!) 下面给出证明:
设
f
(
x
)
=
∑
d
∣
x
g
(
d
)
×
h
(
x
/
d
)
,
有
两
个
互
质
的
正
整
数
n
,
m
。
设f(x)=\sum_{d|x}g(d)\times h(x/d),有两个互质的正整数n,m。
设 f ( x ) = ∑ d ∣ x g ( d ) × h ( x / d ) , 有 两 个 互 质 的 正 整 数 n , m 。
则
我
们
的
目
标
是
证
明
f
(
n
m
)
=
f
(
n
)
×
f
(
m
)
则我们的目标是证明f(nm)=f(n)\times f(m)
则 我 们 的 目 标 是 证 明 f ( n m ) = f ( n ) × f ( m ) 。 我们尝试一下从结论出发,
f
(
n
m
)
=
f
(
n
)
×
f
(
m
)
f(nm)=f(n) \times f(m)
f ( n m ) = f ( n ) × f ( m )
∑
a
b
∣
n
m
g
(
a
b
)
×
h
(
n
m
/
a
b
)
=
(
∑
a
∣
n
g
(
a
)
×
h
(
n
/
a
)
)
×
(
∑
b
∣
m
g
(
b
)
×
h
(
m
/
b
)
)
\sum_{ab|nm}g(ab) \times h(nm/ab)=(~~\sum_{a|n}g(a) \times h(n/a)~~ )\times( ~~ \sum_{b|m}g(b) \times h(m/b) ~)
∑ a b ∣ n m g ( a b ) × h ( n m / a b ) = ( ∑ a ∣ n g ( a ) × h ( n / a ) ) × ( ∑ b ∣ m g ( b ) × h ( m / b ) )
∑
a
b
∣
n
m
g
(
a
)
×
h
(
n
/
a
)
×
g
(
b
)
×
h
(
m
/
b
)
=
(
∑
a
∣
n
g
(
a
)
×
h
(
n
/
a
)
)
×
(
∑
b
∣
m
g
(
b
)
×
h
(
m
/
b
)
)
(
积
性
函
数
的
性
质
得
到
)
\sum_{ab|nm}g(a) \times h(n/a) \times g(b) \times h(m/b)=(~~\sum_{a|n}g(a) \times h(n/a)~~ )\times( ~~ \sum_{b|m}g(b) \times h(m/b) ~)(积性函数的性质得到)
∑ a b ∣ n m g ( a ) × h ( n / a ) × g ( b ) × h ( m / b ) = ( ∑ a ∣ n g ( a ) × h ( n / a ) ) × ( ∑ b ∣ m g ( b ) × h ( m / b ) ) ( 积 性 函 数 的 性 质 得 到 )
因为a,b互质,所以二者互不相干。如果我们把a看作一个常量,那么等式左边可化为
∑
a
∣
n
g
(
a
)
×
h
(
n
/
a
)
×
(
∑
b
∣
m
g
(
b
)
×
h
(
m
/
b
)
)
\sum_{a|n}g(a) \times h(n/a) \times ( ~~ \sum_{b|m}g(b) \times h(m/b) ~)
∑ a ∣ n g ( a ) × h ( n / a ) × ( ∑ b ∣ m g ( b ) × h ( m / b ) ) =
(
∑
a
∣
n
g
(
a
)
×
h
(
n
/
a
)
)
×
(
∑
b
∣
m
g
(
b
)
×
h
(
m
/
b
)
)
(\sum_{a|n}g(a) \times h(n/a) )\times ( ~~ \sum_{b|m}g(b) \times h(m/b) ~)
( ∑ a ∣ n g ( a ) × h ( n / a ) ) × ( ∑ b ∣ m g ( b ) × h ( m / b ) ) 。 (感性理解即可)
我们的每一变换都是恒等变化,所以我们也可以由下推到上,也就证明了这个性质的正确性。
3.用途:
狄利克雷卷积可以用来证明莫比乌斯反演。 除此以外,我们还可以利用狄利克雷卷积的强大性质来加快求和。
例题(POJ2480 Longge’s problem):
Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N. “Oh, I know, I know!” Longge shouts! But do you know? Please solve it.
设
i
d
(
x
)
=
x
id(x)=x
i d ( x ) = x ,
把
d
当
做
g
c
d
(
i
,
n
)
,
把d当做gcd(i,n),
把 d 当 做 g c d ( i , n ) ,
∑
i
=
1
n
g
c
d
(
i
,
n
)
=
∑
i
=
1
n
d
×
[
g
c
d
(
i
/
d
,
n
/
d
)
=
=
1
]
=
\sum_{i=1}^n gcd(i,n)=\sum_{i=1}^n d \times [gcd(i/d,n/d)==1]=
∑ i = 1 n g c d ( i , n ) = ∑ i = 1 n d × [ g c d ( i / d , n / d ) = = 1 ] =
∑
d
∣
n
d
×
∑
i
=
1
n
/
d
[
g
c
d
(
i
,
n
/
d
)
=
=
1
]
=
∑
d
∣
n
d
×
ϕ
(
n
/
d
)
=
i
d
(
n
)
∗
ϕ
(
n
)
\sum_{d|n} d\times \sum_{i=1}^{n/d} [gcd(i,n/d)==1]=\sum_{d|n} d\times \phi(n/d)=id(n)* \phi(n)
∑ d ∣ n d × ∑ i = 1 n / d [ g c d ( i , n / d ) = = 1 ] = ∑ d ∣ n d × ϕ ( n / d ) = i d ( n ) ∗ ϕ ( n ) (狄利克雷卷积) 那么,我们可以直接质因数分解n,利用上面的性质求解。 下面有一个暴力,一个正解。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned int ui;
typedef long long ll;
int p[ 11 ] , s[ 11 ] , n;
ll ans;
void dfs ( int k, int sum, int phi)
{
if ( k> p[ 0 ] )
{
ans+ = n/ sum* phi;
return ;
}
dfs ( k+ 1 , sum, phi) ;
ll x= p[ k] ;
for ( int i= 1 ; i<= s[ k] ; i++ )
{
dfs ( k+ 1 , sum* x, ( ll) phi* ( x/ p[ k] ) * ( p[ k] - 1 ) ) ;
x* = p[ k] ;
}
}
int main ( )
{
while ( ~ scanf ( "%d" , & n) )
{
p[ 0 ] = 0 ;
memset ( s, 0 , sizeof ( s) ) ;
int x= n;
for ( ll i= 2 ; i* i<= x; i++ )
if ( x% i== 0 )
{
p[ ++ p[ 0 ] ] = i;
do
{
x/ = i;
s[ p[ 0 ] ] ++ ;
} while ( x% i== 0 ) ;
}
if ( x> 1 ) p[ ++ p[ 0 ] ] = x, s[ p[ 0 ] ] = 1 ;
ans= 0 ;
dfs ( 1 , 1 , 1 ) ;
printf ( "%lld\n" , ans) ;
}
return 0 ;
}
#include <cstdio>
using namespace std;
typedef long long ll;
ll ans;
int n, p, s;
int main ( )
{
while ( ~ scanf ( "%d" , & n) )
{
ans= 1 ;
for ( ll i= 2 ; i* i<= n; i++ )
if ( n% i== 0 )
{
s= 0 ; p= 1 ;
do
{
n/ = i;
p* = i;
++ s;
} while ( n% i== 0 ) ;
ans* = ( ll) ( s* ( i- 1 ) * p/ i) + p;
}
if ( n> 1 ) ans* = ( ll) ( n- 1 ) + n;
printf ( "%lld\n" , ans) ;
}
return 0 ;
}