zoukankan      html  css  js  c++  java
  • 莫比乌斯函数 && HDU-1695

    莫比乌斯函数定义

    $$mu(d)=egin{cases}
    1 & ext{d = 1}\
    (-1)^r & ext{$d=p_1p_2...p_r,其中p_i为不同的素数$}\
    0 & ext{else}
    end{cases}$$

    性质

    (1)$sum_{d|n}mu(d)=[n=1]$

    (2)$sum_{d|n}frac{mu(d)}{d}=frac{phi(n)}{n}$

    莫比乌斯反演(没写定义域之类的):

    $F(n)=sum_{d|n}f(d)或F(n)=sum_{d|n}f(frac{n}{d}){quad}{Leftrightarrow}{quad}f(n)=sum_{d|n}mu(d)F(frac{n}{d})或f(n)=sum_{d|n}mu(frac{n}{d})F(d)$

    $F(n)=sum_{n|d}f(d){quad}{Leftrightarrow}{quad}f(n)=sum_{n|d}mu(frac{d}{n})F(d)$(一般用的都是这种)
    并不清楚为什么d没有上限

    证明:https://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html

    (性质1根据二项式定理直接证,那么反演公式可以根据性质1证(第二种反演的证法类似第一种反演,式子可以做类似的变换))


    线性筛莫比乌斯函数

    设mu[i]为i的莫比乌斯函数值

    首先,mu[1]=1

    mu[一个质数]=-1

    对于一个合数x,设其最小质因子为p,那么它会被q=x/p筛掉,在它被q筛掉时,判断一下q%p是否为0,如果为0则说明q有至少1个质因子p,因此x有至少2个质因子p,那么mu[x]=0;否则mu[x]=-mu[q]


    模板题:给定i,j,k,求$sum_{i=1}^n{sum_{j=1}^m{[(i,j)=k]}}$

    设$f(x)=sum_{i=1}^n{sum_{j=1}^m{[(i,j)=x]}}$

    设$F(x)=sum_{x|d}{sum_{i=1}^n{sum_{j=1}^m{[(i,j)=d]}}}=sum_{i=1}^n{sum_{j=1}^m{[x|(i,j)]}}$

    显然$F(x)={lfloor}{frac{n}{x}}{ floor}*{lfloor}{frac{m}{x}}{ floor}$

    那么可以根据F(x)计算f(x)得到答案

    (从中看出一类通用的关系:"满足f(a)是x的倍数/因数的a个数""满足f(a)等于x的a的个数"间的转换)


    https://vjudge.net/problem/HDU-1695

    (此题跟以上"模板题"题面类似,但不完全一样,要加一些特判)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pii;
    13 #define N 100100
    14 ll prime[N+100],len,mu[N+100];
    15 bool nprime[N+100];
    16 ll a,c,n,m,k,ans,a2;
    17 ll F(ll x)    {return (m/x)*(n/x);}
    18 ll F2(ll x)    {return (n/x)*(n/x);}
    19 int main()
    20 {
    21     ll i,j,T,TT;
    22     mu[1]=1;
    23     for(i=2;i<=N;i++)
    24     {
    25         if(!nprime[i])    prime[++len]=i,mu[i]=-1;
    26         for(j=1;j<=len&&i*prime[j]<=N;j++)
    27         {
    28             nprime[i*prime[j]]=1;
    29             if(i%prime[j]==0)    {mu[i*prime[j]]=0;break;}
    30             else    mu[i*prime[j]]=-mu[i];
    31         }
    32     }
    33     scanf("%lld",&T);
    34     for(TT=1;TT<=T;TT++)
    35     {
    36         scanf("%lld%lld%lld%lld%lld",&a,&n,&c,&m,&k);
    37         if(n>m)    swap(n,m);
    38         ans=a2=0;
    39         if(k>n||k==0)    goto xxx;
    40         for(i=1;i<=n/k;i++)
    41             ans+=mu[i]*F(i*k);
    42         for(i=1;i<=n/k;i++)
    43             a2+=mu[i]*F2(i*k);
    44         ans-=(a2-1)/2;
    45         xxx:;
    46         printf("Case %lld: %lld
    ",TT,ans);
    47     }
    48     return 0;
    49 }
    View Code

    另外:此题也可以不用莫比乌斯函数做,可以直接容斥

    简单来讲就是先算出数组F,其中F[i]=F(i)

    然后预处理出n个vector(d1,d2,..,dn),第i个表示i的所有因子(用枚举每个数的倍数的方式,而不是枚举因子)

    然后从大到小枚举i,对于i除自身外所有的因子j,F[j]-=F[i]

    对此题并没有什么特别的好处。。只是记一下有这种方法

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pii;
    13 #define N 100100
    14 ll an[N+100];
    15 ll a,c,n,m,k,ans,a2;
    16 ll F(ll x)    {return (m/x)*(n/x);}
    17 ll F2(ll x)    {return (n/x)*(n/x);}
    18 vector<ll> d[100100];
    19 int main()
    20 {
    21     ll i,j,T,TT;
    22     for(i=1;i<=100000;i++)
    23         for(j=2*i;j<=100000;j+=i)
    24             d[j].pb(i);
    25     scanf("%lld",&T);
    26     for(TT=1;TT<=T;TT++)
    27     {
    28         scanf("%lld%lld%lld%lld%lld",&a,&n,&c,&m,&k);
    29         if(n>m)    swap(n,m);
    30         ans=a2=0;
    31         if(k>n||k==0)    goto xxx;
    32         for(i=1;i<=n;i++)    an[i]=F(i);
    33         for(i=n;i>=1;i--)
    34             for(j=0;j<d[i].size();j++)
    35                 an[d[i][j]]-=an[i];
    36         ans+=an[k];
    37         for(i=1;i<=n;i++)    an[i]=F2(i);
    38         for(i=n;i>=1;i--)
    39             for(j=0;j<d[i].size();j++)
    40                 an[d[i][j]]-=an[i];
    41         a2+=an[k];
    42         ans-=(a2-1)/2;
    43         xxx:;
    44         printf("Case %lld: %lld
    ",TT,ans);
    45     }
    46     return 0;
    47 }
    View Code

    资料待看:

    https://www.cnblogs.com/chenyang920/p/4811995.html

    https://blog.csdn.net/danliwoo/article/details/51866867

  • 相关阅读:
    服务器时钟同步
    vue父组件向子组件传递数值 props
    sql 语句in 使用占位符
    vagrant 打包box 快速部署统一开发环境
    Memcache安装使用 linux系统
    centos 7 搭建lnmp环境搭建 yum 源安装
    vagrant搭建lnmp 环境(环境contos7+php72w+mariaDB10.2)
    linux定时任务 Cron Crontab命令
    vue使用el-upload 跨域上传文件跳坑小记
    vue key得理解
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9296975.html
Copyright © 2011-2022 走看看