0.前置知识
一些函数
- (1(n)=1)
- (id(n)=n)
- (sigma(n))为(n)的约数和
狄利克雷卷积
定义两个数论函数运算(*),
若(h=f*g),则
[h(n)=sum_{d|n}f(d)g(frac nd)
]
它满足一些性质:
-
(f*g=g*f)
-
(f*(g*h)=(f*g)*h)
因为(sum_{(ij)k=n}(f(i)g(j))h(k)=sum_{i(jk)=n}f(i)(g(j)h(k)))
-
((f+g)*h=f*h+g*h)
-
((xf)*g=x(f*g))
-
设单位元(epsilon(n) = [n = 1]),则(epsilon*f=f)
-
对于每个(f(1) eq 0)的函数(f),存在逆元(g)使得(f*g=epsilon)
如何求一个函数的逆元呢?
令(g(n))满足以下式子:
[g(n)=frac 1{f(1)}left(epsilon(n)-sum_{i|n,i
eq1}f(i)g(frac ni)
ight)
]
这样的话:
[sum_{i|n}f(i)g(frac ni) \
=f(1)g(n) + sum_{i|n, i
eq 1} f(i)g(frac ni) \
=epsilon(n) \
herefore f*g=epsilon
]
1.莫比乌斯反演
定义一个函数(mu)使得(mu*1=epsilon)
这样的话,如果(g*1=f),则(f*mu=g)
即:如果(f(n)=sum_{d|n}g(d)),则(g(n)=sum_{d|n}mu(d)f(frac nd))
是不是很简单
2.题目
若(n<m)求:
#1
[sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=1]
]
设(f=epsilon),(ecause epsilon=1*mu,; herefore g=mu)
于是原式变为:
[sum_{i=1}^nsum_{j=1}^msum_{d|i,d|j}mu(d) \
=sum_{d=1}^n mu(d)sum_{i=1}^nsum_{j=1}^m[d|i][d|j] \
=sum_{d=1}^n mu(d)left[frac nd
ight]left[frac md
ight]
]
预处理(mu),数论分块就可以(O(sqrt n))求了
#2
[sum_{i=1}^nsum_{j=1}^m gcd(i,j)
]
设(f=id),(ecause id=1*varphi,; herefore g=varphi)
于是原式变为:
[sum_{d=1}^nvarphi(d)left[frac nd
ight]left[frac md
ight]
]
#3
[sum_{i=1}^nsum_{j=1}^msigma(gcd(i,j))
]
设(f=sigma),(ecausesigma=1*(mu*sigma),; herefore g=mu*sigma)
于是原式变为:
[sum_{d=1}^ng(d)left[frac nd
ight]left[frac md
ight]
]
因为积性函数可以线性筛,所以也可以预处理
#4
[sum_{i=1}^nsum_{j=1}^mf(gcd(i,j))
]
设(g=mu*f),如果我们能预处理出(f),那么可以这样求(g)
(当然是蒯的啦)
void get_g_1(int N, const int *f, int *g)
{
for (int i = 1; i <= N; i++) g[i] = 0;
for (int i = 1; i <= N; i++)
for (int j = 1; i * j <= N; j++)
g[i * j] = (g[i * j] + mu[i] * f[j]) % mod;
} // 依照定义,O(nlogn)
void get_g_2(int N, const int *f, int *g)
{
for (int i = 1; i <= N; i++) g[i] = f[i];
for (int i = 1; i <= N; i++)
for (int j = 2; i * j <= N; j++)
g[i * j] = (g[i * j] - g[i]) % mod;
} // 类似求狄利克雷卷积逆的方式,不需要线性筛 mu ,O(nlogn)
void get_g_3(int N, const int *f, int *g)
{
for (int i = 1; i <= N; i++) g[i] = f[i];
for (int i = 0; i < prime_count; i++)
for (int j = N / prime[i]; j >= 1; j--)
g[j * prime[i]] = (g[j * prime[i]] - g[j]) % mod;
} // Magic! O(nloglogn)
于是原式变为:
[sum_{d=1}^ng(d)left[frac nd
ight]left[frac md
ight]
]