zoukankan      html  css  js  c++  java
  • 莫比乌斯反演

     

         在acm-icpc程序设计系列上这一块基本是点到即止,只给了公式和几个简单例子,没怎么给应用。而网上复制黏贴的居多,都是难以理解的博客内容。功夫不负有心人,终于找到一个尽心尽责的博客:

    http://blog.sina.com.cn/s/blog_76f6777d0101bi0z.html(参考一部分) 

      这个反演放在容斥定理这一块是有一定道理的,它是偏序集的容斥定理公式延伸出来的东西。

      废话不多说,开始数学玄学的探索。

         first 

      首先是偏序集的容斥定理公式:

      

        这个公式即对于偏序集<A,<=>有运算g(A),他由A的所有子集S作f(s)运算而得(假设g(x)已知f(x)未知),那么f(A)即为对所有s作g(x)运算并乘以(-1)^(|A|-|S|))(|A|为A集合中元素个数.基数)的和,反演推理出f(x)的值。当g(x)=|x|时,就类似于容斥原理了。只不过容斥原理是几个子集Pi且Pi的交集为A,而这是A的所有子集。

      下面给出证明,参考该博客的公式证明:

      

      【注意 第四行 R 属于 S-T 其实应该是  R属于 A-T.. 懒得改了..】

      3—>4:3 是将所有包含于s的T进行了f运算然后乘p=(-1)^|R|再将所有按照各s进行求和,四则是把上面的运算顺序调换,对于每个,T先将T被包含于的S进行|R|=|A-S|求和,然后在把答案乘f(T)按照各T进行求和。

         

      4->5 :

        当T=A,即A-T为空集时,R只能为空集,sigma (-1)^|R| =1,  即 f(T=A) 在式子中被累加一次.

        当T!=A时,即A-T为非空集,把每个|R|=k的(k 属于 [0,|A-T|])放到一起算..有 :

        Σ[R属于A-T](-1)^|R|= Σc(|A-T|,k)*(-1)^k =(1-1)^|A-T|=0..由二项式定理得 =0 . 所以这些f(T!=A) 均不被累加.

         所以化成了第5行.

       second

      接下来就是莫比乌斯反演了:  

        由于类似整除关系是满足是偏序关系..所以也可以用上述容斥原理..

    先是公式(数用大写表示不大适合的样子..但为了与上面的对应..恩)

    g(A)=sigma[S|A] f(S)

    f(A)=sigma [S|A] miu(A/S) * g(S)

        把 a|b看做 a属于b,a-b看成a/b,a+b(a并b)看成a*b,其实就一样了..

    miu(d)的取值,可以用容斥原理来理解.. 写一下f(60)什么的会发现..这里的减少一个元素的子集,就是剔除一个质因数,然后因为就算的时候不会重,所以第一次时剔除的质因数不会相同,那么后面所构成的数(也就是前面所构成的并),分解质因数后,也不会有质因数相同.

        或者我们用上面证明极类似的方法.. 可以顺便说明 miu(d)的取值 :

    sigma [S|A] miu(A/S) * g(S)=sigma[T|A]( f(T) * sigma[S|A,T|S] miu(A/S) )

        现在要使:

    T=A时, 后面的sigma=1,由于此时只有 T=S=A, 所以sigma=1=miu(A/S)=miu(1) ,即miu(1)=1

    T!=A时,与上面类似的构造R=A/S,R| (A/T) ,对于每个R,有S=A/R 一 一对应,且 必有 T|S,式子化成了

    sigma [T|A] f(T)*sigma[R|(A/T)] miu(R)

    由于T|A,T!=A, 首先 (AT) >1 .. 要尽量在满足这个的情况下,使这个=0. miu(R)也是类似等于|R|,即R包含的元素个数. 元素个数具体是什么? 首先,由于上面的每个元素是视作不同的,才可以直接用c(,)而不去重.. 而如果有重的,这里式子中实际只会算一次,所以 这些元素是要不一样的.. 

    ->想到 若 d=p1p2..pn且每个质因数恰一个的情况下,miu(d)= (-1)^n . 其他情况除了miu(1)=1,都为0

       若此时 R=p1^x1 * p2^x2..* pm^xm,同样把取到的每个质因数只有一个的满足 d|R的d, 把 质因数个数为n的放一起算.. sigma[R|(A/T)] miu(R) = miu(1)+ sigma[1<=n<=m] c(m,n)*(-1)^n =0

    就又有 原式=f(A)了..

      


    2016-09-16 21:38:46 

     时隔半年继续拾起当年的莫比乌斯反演。感谢贾志鹏大大的pdf让我看懂了莫比乌斯反演跟容斥原理的真正关系,以及一些函数用线性筛的快速求法:

    贾志鹏大大的pdf传送门

    下面是利用线性筛求一些函数从1-n的所有值得O(n)算法的模板:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define clr(x) memset(x,0,sizeof(x))
     5 using namespace std;
     6 int mu[100000];
     7 int inf[100000];
     8 int prime[100000];
     9 int tot;
    10 void  done(int n)
    11 {
    12     clr(prime);
    13     clr(inf);
    14     clr(mu);
    15     mu[1]=1;
    16     tot=0;
    17     for(int i=2;i<=n;i++)
    18     {
    19         if(!inf[i])
    20         {
    21             prime[tot++]=i;
    22             inf[i]=1;
    23             mu[i]=-1;
    24         }
    25         for(int j=0;j<tot;j++)
    26         {
    27             if(i*prime[j]>n) break;
    28             inf[i*prime[j]]=1;
    29             if(i%prime[j]==0)
    30             {
    31                 mu[i*prime[j]]=0;
    32                 break;
    33             }
    34             else
    35             {
    36                 mu[i*prime[j]]=-mu[i];
    37             }
    38         }
    39     }
    40     return ;
    41 }
    42 int main()
    43 {
    44     int n;
    45     scanf("%d",&n);
    46     done(n);
    47     for(int i=1;i<=n;i++)
    48     {
    49         printf("%d ",mu[i]);
    50     }
    51     printf("
    ");
    52     return 0;
    53 }
    线性筛求莫比乌斯函数
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define clr(x) memset(x,0,sizeof(x))
     5 using namespace std;
     6 int inf[100000];
     7 int prime[100000];
     8 int tot;
     9 void  done(int n)
    10 {
    11     clr(prime);
    12     clr(inf);
    13     tot=0;
    14     for(int i=2;i<=n;i++)
    15     {
    16         if(!inf[i])
    17         {
    18             prime[tot++]=i;
    19             inf[i]=1;
    20         }
    21         for(int j=0;j<tot;j++)
    22         {
    23             if(i*prime[j]>n) break;
    24             inf[i*prime[j]]=1;
    25             if(i%prime[j]==0)
    26                 break;
    27         }
    28     }
    29     return ;
    30 }
    31 int main()
    32 {
    33     int n;
    34     scanf("%d",&n);
    35     done(n);
    36     for(int i=0;i<tot;i++)
    37     {
    38         printf("%d ",prime[i]);
    39     }
    40     printf("
    ");
    41     return 0;
    42 }
    线性筛求质数
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define clr(x) memset(x,0,sizeof(x))
     5 using namespace std;
     6 int inf[100000];
     7 int eu[100000];
     8 int prime[100000];
     9 int tot;
    10 void  done(int n)
    11 {
    12     clr(prime);
    13     clr(inf);
    14     tot=0;
    15     for(int i=2;i<=n;i++)
    16     {
    17         if(!inf[i])
    18         {
    19             prime[tot++]=i;
    20             inf[i]=1;
    21             eu[i]=i-1;
    22         }
    23         for(int j=0;j<tot;j++)
    24         {
    25             if(i*prime[j]>n) break;
    26             inf[i*prime[j]]=1;
    27             if(i%prime[j]==0)
    28             {
    29                 eu[i*prime[j]]=eu[i]*prime[j];
    30                 break;
    31             }
    32             else
    33                 eu[i*prime[j]]=eu[i]*(prime[j]-1);
    34         }
    35     }
    36     return ;
    37 }
    38 int main()
    39 {
    40     int n;
    41     scanf("%d",&n);
    42     done(n);
    43     for(int i=1;i<=n;i++)
    44     {
    45         printf("%d ",eu[i]);
    46     }
    47     printf("
    ");
    48     return 0;
    49 }
    线性筛求欧拉函数
  • 相关阅读:
    Get distinct count of rows in the DataSet
    单引号双引号的html转义符
    PETS Public English Test System
    Code 39 basics (39条形码原理)
    Index was outside the bounds of the array ,LocalReport.Render
    Thread was being aborted Errors
    Reportviewer Error: ASP.NET session has expired
    ReportDataSource 值不在预期的范围内
    .NET/FCL 2.0在Serialization方面的增强
    Perl像C一样强大,像awk、sed等脚本描述语言一样方便。
  • 原文地址:https://www.cnblogs.com/wujiechao/p/5484222.html
Copyright © 2011-2022 走看看