zoukankan      html  css  js  c++  java
  • 莫比乌斯函数

    前言

    前言

    本文内容大部分来自Oier PoPoQQQ 的课件。
    onedrive, baidu
    pan
    ,密码:6ug5

    本文基本上由我学习相当于是制作的一篇学习笔记,但是将课件中的一些不完善的地方加以完善
    使得更容易理解,加上了部分例题的代码

    引子

    介绍莫比乌斯反演之前我们先来看一个函数

    根据的定义

    于是我们便可以通过推导出

    在推导的过程中我们是否发现了一些规律?

    莫比乌斯反演

    莫比乌斯反演[1]

    莫比乌斯反演定义

    其中为莫比乌斯函数[1],定义如下

    莫比乌斯函数的定义式[2]

    莫比乌斯函数的性质

    (1)

    当n不等于1时,n所有因子的莫比乌斯函数值的和为0,

    那么

    证明:

    (2)

    对于有:

    (3)

    积性函数 数论上积性函数的定义

    积性函数的性质

    积性函数的前缀和也是积性函数

    因为积性函数是积性函数,

    因此可以通过线性筛求出莫比乌斯函数的值

    mu[1]=1;
    for(i=2;i<=n;i++){
        if(!not_prime[i]){
            prime[++tot]=i;
            mu[i]=-1;
        }
        for(j=1;prime[j]*i<=n;j++){
            not_prime[prime[j]*i]=1;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
    

    例题1:

    BZOJ 2440
    完全平方数

    题目大意:求第k个无平方因子数[3]

    做法:
    首先二分答案,问题转化为求之间有多少个无平方因子数
    根据容斥原理可知,对于之内所有的质数,
    答案G(x)=0个质数平方倍数的个数-1个质数平方倍数的个数+2个质数平方倍数的个数-...,
    那么对于偶数个质数平方对于答案的贡献就是正的,否则是负的,
    如果不是若干个互异质数的乘积,那么对答案没有影响,

    如何表示这个式子呢?

    观察莫比乌斯函数的定义[1],可以知道对于能对答案产生贡献的数,其中分解得到质数的个数
    根据上述说明,那么可以得知结果

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define N 100005
    using namespace std;
    

    bool not_prime[N];
    int prime[N];
    int mu[N];
    int tot;

    void Mu(int n){
    int i,j;
    mu[1]=1;
    for(i=2;i<=n;i++){
    if(!not_prime[i]){
    prime[++tot]=i;
    mu[i]=-1;
    }
    for(j=1;prime[j]i<=n;j++){
    not_prime[prime[j]
    i]=1;
    if(i%prime[j]==0){
    mu[prime[j]i]=0;
    break;
    }
    mu[prime[j]
    i]=-mu[i];
    }
    }
    }
    int can(int x){
    int sum=0;
    int s=floor(sqrt(x));
    for(int i=1;i<=s;++i)
    if(mu[i])
    sum+=mu[i]floor(x/(ii));
    return sum;
    }

    int main(){
    Mu(N);int T,sum;
    scanf("%d",&T);
    while(T--){
    scanf("%d",&num);
    long long l=1,r=num<<1,mid;
    while(l<r){
    mid=(l+r)>>1;
    if(can(mid)<num)
    l=mid+1;
    else r=mid;
    }
    printf("%lld ",r);
    }
    return 0;
    }

    莫比乌斯反演定理的证明

    证明:

    形式二:

    证明同理,一般要用到的都是这种形式

    莫比乌斯反演的应用

    对于一些函数,如果我们很难直接求出它的值,而容易求出倍数和或约数和,

    那么我们可以直接利用莫比乌斯反演来求得的值

    例:

    f(n)表示某一范围内(x,y)=n的数对的数量,

    F(n)表示某一范围内n|(x,y)的数对的数量

    那么直接求f(n)并不是很好求,而F(n)求起来相对无脑一些,

    那么我们可以通过对F(n)进行莫比乌斯 反演来求得f(n)</p>

    例题2:

    BZOJ 2301 Problem

    b

    题目大意:询问有多少对满足

    根据容斥原理,这个题目就可以转化成

    其中答案为</p>

    那么我们需要快速求出

    这个式子可以进一步转化为

    考虑莫比乌斯反演, 令

    分析可知这个算法的复杂度是

    我们还需要对这个算法进行进一步优化

    因为至多只有个取值,

    那么至多只有个取值

    因为使得成立的值都是连续的,

    所以可以维护一个莫比乌斯函数的前缀和,

    这样就可以在的时间内出解

    枚举除法的取值在莫比乌斯反演的应用当中非常常用

    if(a>b)swap(a,b);
    for(i=1;i<=a;i=last+1){
    last=min(a/(a/i),b/(b/i));
    re+=(a/i)(a/i)(sum[last]-sum[i-1]);
    }
    return re;

    代码异常好写

    #include<iostream>

    include<cstdio>

    include<cmath>

    define N 50005

    define inf 0x7fffffff

    using namespace std;

    bool not_prime[N];
    int prime[N];
    int sum[N];
    int mu[N];
    int tot;

    void Mu(int n){
    int i,j;
    mu[1]=1;
    for(i=2;i<=n;i++){
    if(!not_prime[i]){
    prime[++tot]=i;
    mu[i]=-1;
    }
    for(j=1;prime[j]i<=n;j++){
    not_prime[prime[j]
    i]=1;
    if(i%prime[j]==0){
    mu[prime[j]i]=0;
    break;
    }
    mu[prime[j]
    i]=-mu[i];
    }
    }
    for(int i=1;i<=n;++i)
    sum[i]=sum[i-1]+mu[i];
    }
    int ans(int n,int m){
    if(n>m)swap(n,m);
    int last,i,re=0;
    for(i=1;i<=n;i=last+1){
    last=min(n/(n/i),m/(m/i));
    re+=(n/i)(m/i)(sum[last]-sum[i-1]);
    }
    return re;
    }

    int main(){
    Mu(N);
    int T;
    int a,b,c,d,k;
    scanf("%d",&T);
    while(T--){
    scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    a--;c--;
    a/=k;b/=k;c/=k;d/=k;
    int Ans=ans(b,d)-ans(a,d)-ans(b,c)+ans(a,c);
    printf("%d ",Ans);
    }
    return 0;
    }

    BZOJ 10s但是luogu却莫名WA

    全部加上long long 之后总算是过了

    百思不得其解

    例题3

    BZOJ 2820

    YY的GCD


    题目大意:求有多少数对满足满足为质数

    做法:


    [1] baike:莫比乌斯反演是数论数学中很重要的内容,可以用于解决很多组合数学的问题。

    [2]

    [3] 无平方因子数(Square-Free

    Number),即分解之后所有质因数的次数都为1的数

  • 相关阅读:
    BZOJ 1391: [Ceoi2008]order
    BZOJ 4504: K个串
    2019 年百度之星·程序设计大赛
    POJ 2398 Toy Storage (二分 叉积)
    POJ 2318 TOYS (二分 叉积)
    HDU 6697 Closest Pair of Segments (计算几何 暴力)
    HDU 6695 Welcome Party (贪心)
    HDU 6693 Valentine's Day (概率)
    HDU 6590 Code (判断凸包相交)
    POJ 3805 Separate Points (判断凸包相交)
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/8012843.html
Copyright © 2011-2022 走看看