莫比乌斯函数定义

$$\mu(d)=\begin{cases}
1 &\text{d = 1}\\
(-1)^r &\text{$d=p_1p_2...p_r,其中p_i为不同的素数$}\\
0 &\text{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

莫比乌斯函数 && HDU-1695

(性质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}}{\rfloor}*{\lfloor}{\frac{m}{x}}{\rfloor}$

那么可以根据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\n",TT,ans);
47     }
48     return 0;
49 }
View Code

相关文章: