莫比乌斯(mobius)笔记

来源:互联网 发布:好心分手 知乎 编辑:程序博客网 时间:2024/05/21 19:37

mobius反演的本质是容斥原理,这在《组合数学》里面有提到

基本公式定理

  1. mobius反演公式

    F(n)f(n)=dnf(d)=dnμ(n/d)F(d)=dnμ(d)F(n/d)

    另一种描述:

    F(d)f(d)=dnf(n)=dnF(n)μ(n/d)

  2. 经典公式

    nϕ(n)dnμ(d)=dnϕ(d)=dnμ(d)nd=(n==d)

线性筛

我们可以用线性筛法处理积性函数,简单的说就是用每次用合数最小质因子去筛掉它,这能保证O(n)的时间复杂度,详细的证明请见文末参考文献。可是对于和性的函数我们也可以这样晒去.

void monius(){    cnt =0;    mu[1] = 1;    memset(prime,0,sizeof(prime));    for(int i = 2 ; i<maxn ; ++i){        if(!prime[i]){            prime[cnt++] = i;            mu[i] =-1;        }        for(int j=0 ; j<cnt && i*prime[j]<maxn ; ++j){            prime[i*prime[j]] = 1;            if(i%prime[j])mu[prime[j]*i] = -mu[i];            else {                mu[i*prime[j]] = 0;                break;            }        }    }    sum_mu[0] = 0;    for(int i=1 ; i<maxn ; ++i)        sum_mu[i] = sum_mu[i-1]+mu[i];}
void phi_table(){    cnt =0;    phi[1] = 0;    memset(prime,0,sizeof(prime));    for(int i = 2 ; i<maxn ; ++i){        if(!prime[i]){            prime[cnt++] = i;            phi[i] =i-1;        }        for(int j=0 ; j<cnt && i*prime[j]<maxn ; ++j){            prime[i*prime[j]] = 1;            if(i%prime[j])phi[prime[j]*i] = phi[i]*(phi[prime[j]]);            else {                phi[i*prime[j]]= phi[i]*prime[j];                break;            }        }    }}

分块求和

如果说计算式中出现了 if(i)g((n/i)),则由于 ni的取值只有 O(n) 种显然我们可以运用分段求和(可以打印出这样的值来看一下)记录f的前缀和,然后g就进行分段求和.
这是mobius中的常见的优化.

ll F(int n, int m, int d) {    if (n > m) swap(n, m);    ll ans = 0;    n /= d, m /= d;    for (int i = 1, last = 1; i <= n; i = last + 1) {        last = min(n / (n / i), m / (m / i));        ans += (ll)(sum[last] - sum[i - 1]) * (n / i) * (m / i);    }    return ans;}

gcd相关

mobius最广的应用就是gcd相关的求和问题.

aN,bMgcd(a,b)=1

f(d)=:gcd(a,b)=d(aN,bM),F(d)=:dgcd(a,b).显然有

F(d)F(d)f(d)=N/dM/d=dgcd(a,b)=nf(n)=dnμ(n/d)F(n)=x=1N/du(x)F(dx)=x=1N/du(x)NdxMdx

显然将d设为就是求解d为1的问题,同时,若d为1我们也可以将其转化为N/d,M/d规模下d=1的问题.,不过需要说明的问题是我们可以用分块求和这样就能在n的复杂度解决这个问题了.
例题:
2301
格点可视性问题

f(d)N/dd|nF(n)

这个就必修使用双分套分块求和以达到O(n)的复杂度了.
可以参考文献3.
例题:
能量采集

筛出每一个gcd(a,b)=d的个数 d=1,2,,n

这个题目不需要mobius也能解决,主要是筛法应用.
题目:
GCD of Sequence.

参考
从N往1,运用筛法O(nlgn)

一个分块求和的例子

Mophues
这个题目就是用了分块求和,求出对于每一个计算N/j的mobius贡献,再运用分块求和再n处理询问.

参考文献:

贾智鹏 线性筛
ACDreamer
sengxian’s blog

0 0
原创粉丝点击