莫比乌斯反演

今天凌晨学习了莫比乌斯反演,来总结下具体思路。
主(所)要(有)的内容都来自于
http://97littleleaf11.xyz/oi/dirichlet_convolution/#i-7


1.狄利克雷卷积
定义两个函数 f g的狄利克雷卷积为:

(fg)(n)=d|nf(d)g(nd)

显然狄利克雷卷积满足交换律,结合律和加法的分配律
2.单位元
狄利克雷卷积的单位元,即满足以下条件的函数:
aI=Ia=a

那么,则知道:
I(n)=[n=1]

3.反演
设:
ab=I

则有:
f=ag  <=> g=bf

这个根据单位元和等式的性质可以得出。
那么:
f(n)=d|na(d)g(nd) <=> g(n)=d|nb(d)f(nd)


4.莫比乌斯函数
莫比乌斯函数是这样的函数:
if(n==1)μ(n)=1
if(n==p1p2p3...pk)μ(n)=(1)k
if(n>=2)μ(n)=0
<这是一个不会用Latex的智障写的>
5.莫比乌斯函数性质

d|nμ(d)=[n=1]

证明:
在n = 1时显然成立。
假设n的素数分解形式: n=Πki=0peii
考虑到如果 d 的分解形式如果是含有平方因子的,那么就是0了,即所有有效的d都是在 k 个质数中选出i个不同的.所以我们实质上是从大小为 k 的集合中选出i个数作为 d 。即要证明:
i=0k(ki)(1)i=0

i=0k(ki)(1)i1ki=0

二项式定理逆用:
i=0k(ki)(1)i1ki=(11)k=0

6.莫比乌斯反演
终于进入正题了么……
考虑莫比乌斯函数的逆函数 e (这个词是我编出来的)
即:
μe=I

我们可以知道 e(n)=1 .
即对于任意的n, e(n)=1
我们现在要证明的是:
f(n)=d|ng(d)  <=>g(n)=d|nμ(d)f(nd)

由普通的反演,我们知道了这个:
f(n)=d|na(d)g(nd) <=> g(n)=d|nb(d)f(nd)

我们可以把 f 写成卷积的形式:f(n)=eg=d|ne(d)g(nd)
我们知道 eμ=I
那么把普遍的反演的 b(d) 就可以换成 μ(d) 了。
这样就证明完毕了。


我们知道莫比乌斯反演的第一种形式是:

f(n)=d|ng(d)<=>g(n)=d|nμ(d)f(nd)

莫比乌斯反演还有另外一种形式:
f(n)=n|dg(d)  <=>g(n)=n|dμ(dn)f(d)

如果第一个形式把n除以d写成d,把d写成n除以d好像还可以救……然而第二个……
证明:
PoPoQQQ:证明同理。


证明:
k=dn

g(n)=k=1μ(k)f(nk)=k=1μ(k)nk|tg(t)

我们注意到,对于 t=pn , μ(k)g(t) 会被结算 k|p 次.
所以我们改写一下:
g(n)=n|tg(t)k|tnμ(k)

注意到 k|tnμ(k) 的值,当且仅当 tn=1 的时候,即 t=n 的时候 k|tnμ(k)=1
其余时刻都等于0.
那么我们知道:
这样把 t=n 带入之后就证明完毕了。


重新回顾下两个公式:

f(n)=d|ng(d)  <=>g(n)=d|nμ(d)f(nd)

f(n)=n|dg(d)  <=>g(n)=n|dμ(dn)f(d)


然后就可以刷水题辣,开心。


据说,只需要 d|nμ(n)=[n=1] 就可以做题了。
真的么……?
显然是真的呀QAQ
比如:

ij[gcd(i,j)=1]=ijd|gcd(i,j)μ(d)

看上去好像变复杂了?
但是实际上是变简单了吧QAQ


你们绝对不会想到我在这里写关于欧拉函数的东西
1.求 pk 的欧拉函数值(p为素数):
显而易见, pk 中与 pk gcd 不为1的只有含有 p 的数,即:pk1
φ(pk)=pkpk1
2.求 pq 的欧拉函数值(p和q互素)
感觉很显然是积性的但是好像真的只是民科思路……?
因为与 pq 互素的数既不能有 p 的因子,又不能有q的因子。
即:既与 p 互素又与q互素。
那么把phi(p)的数和phi(q)的数进行组合即可。
3.经过上面的东西,我们知道:

phi(n)=nΠ(11pi)

那么我们可以在 O(n) 的时间复杂度内计算一个数的欧拉函数。
O(n) 的时间内计算1~n的欧拉函数。

//计算单个数的phi值
int phi(int n)
{
    int tmp = n;
    for(int i = 2;i * i <= n;++ i)
    {
        if(n % i == 0)
        {
            while(n % i == 0)n /= i;
            tmp = tmp / i * (i - 1);
        }
    }
    if(n > 1)tmp = tmp / n * (n - 1);
    return tmp;
}

线性筛的代码最后放出。
4.欧拉定理:

if (a,p)=1 then:aφ(p)1 mod p

5.欧拉定理推论:
if (a,p)=1 then:aqaq % φ(p) mod p


int m,n,mu[1000005],phi[10000005],cnt,p[20000005];
bool sp[10000005];
void Get()
{
    int i,j;
    phi[1] = mu[1] = 1;
    phi[1] = 0;
    n = 10000000;
    for(i = 2;i <= n;++ i)
    {
        if(!sp[i])phi[i] = i - 1,mu[i] = -1,p[++ cnt] = i;
        for(j = 1;j <= cnt && 1ll * i * p[j] <= n;++ j)
        {
            sp[p[j] * i] = 1;
            if(!(i % p[j]))
            {
                phi[i * p[j]] = p[j] * phi[i];
                mu[i * p[j]] = 0;
                break;
            }
            else 
            {
                mu[i * p[j]] = -mu[i];
                phi[i * p[j]] = phi[i] * phi[p[j]];
            }
        }
    }
}

Upd On 2016/8/29
三个问题:
1.Q次询问,每次询问a<=x<=b,c<=y<=d里面的(x,y) = k的有多少个。
题解:
把询问可以用容斥原理拆成四个。
这样就考虑[1,m],[1,n]里面有多少个gcd(i,j) = k.
即: [1,m/k],[1,n/k] 里面有多少个gcd(i,j) = 1.

f(n,m)=ij[gcd(i,j)=1]

f(n,m)=ijd|gcd(i,j)μ(d)

f(n,m)=dμ(d)[nd][md]

分块并维护莫比乌斯前缀和即可。
2.Q次询问,每次询问1<=x<=n,1<=y<=m里面的(x,y)为质数的有多少个。
pij[gcd(i,j)=p]

pdμ(d)[npd][mpd]

T=pd

TnTmTp|Tμ(Tp)

显而易见可以筛 p|Tμ(Tp) ,这样又可以分块了。
3.有一张n×m的数表,其第i行第j列(1 <=i <=n,1 <=j<= m)的数值为能同时整除i和j的所有自然数之和。Q次询问,每次给定a,计算数表中不大于a的数之和。
ij[d(gcd(i,j))<=a]d(gcd(i,j))

T[d(T)<=a]d(T)[nT][mT]

用主席树维护前缀和即可。(或许)


为什么没有代码呢……?
这个……
显然是我写错了啊。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值