莫比乌斯反演入门
来源:互联网 发布:淘宝店铺整体托管 编辑:程序博客网 时间:2024/05/21 08:48
首先…
我们来了解一下什么是莫比乌斯反演……
假设有两个函数
也就是
f(1)=g(1) f(2)=g(1)+g(2) f(3)=g(1)+g(3) f(4)=g(1)+g(2)+g(4) f(5)=g(1)+g(5) f(6)=g(1)+g(2)+g(3)+g(6)
.
.
.
求
列一下
g(1)=f(1) g(2)=−f(1)+f(2) g(3)=−f(1)+f(3) g(4)=−f(2)+f(4) g(5)=−f(1)+f(5) g(6)=−f(1)−f(2)−f(3)+f(6)
.
.
.
???
继续列下去(本人过于懒惰)
似乎
而且,这个
我们暂且将这个函数设为
并且这个函数的取值只有
光这么看很难发现这个函数的规律,然而我们的大数学家莫比乌斯发现了(不然怎么叫莫比乌斯反演)
式子是这样的
第二条就是至少有一个
所以我们就有
这条式子也可以这么写
这个函数就是莫比乌斯函数
证明?
首先,莫比乌斯函数有几个性质。
- 性质一
∑d|nμ(d)=0|n∈N∗,n>1 ∑d|nμ(d)=1|n=1 - 性质二 莫比乌斯函数是积性函数
gcd(p,q)=1,μ(p)∗μ(q)=μ(p∗q)
先证性质一。
设
显然
那么设
所以
我们有二项式定理
得证!
性质二似乎比较显然,此处不准备证明。
然后我们来证明反演。
然后我们运用一种叫交换主体的等价变换,就是将后面的
下面直接是交换后的,想想为什么?
不急,因为我们有性质一
当
当
综上
应用
然而莫比乌斯函数怎么求?
可以用线性筛法!
void getprime(int lim){ int i,j,num=0; fo(i,2,lim) { if (!bz[i]) { prime[++num]=i; mu[i]=-1;//质数就是一个质因子 } for(j=1;i*prime[j]<=lim&&j<=num;j++) { bz[i*prime[j]]=1; if (prime[j]==i) break; if (!(i%prime[j])) { mu[i*prime[j]]=0; //显然prime[j]在i*prime[j]中指数大于等于2 break; } mu[i*prime[j]]=-mu[i];//多加了一个质因子乘上-1 } }}
事实上,莫比乌斯反演还有个变形
若
则
证明类似上面的证法,此处不再赘述。若有兴趣着可以参考度娘。
它可以非常好的应用在一些问题,比如说
例题([HAOI2011][BZOJ2301]Problem b)
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
我们有这个
设
设
那么显然有
故
这里可能会超时,所以对于
附代码
#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;long long mu[50005];int a,b,c,d,k;int prime[50005],n;bool bz[50005];void getprime(int lim){ int i,j,num=0; fo(i,2,lim) { if (!bz[i]) { prime[++num]=i; mu[i]=-1; } for(j=1;i*prime[j]<=lim&&j<=num;j++) { if (i*prime[j]>50000) break; bz[i*prime[j]]=1; if (prime[j]==i) break; if (!(i%prime[j])) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } }}int find(int k,int mx,int my){ int i=1,j; long long ans=0; while(i<=trunc(min(mx,my)/k)) { j=min(mx/(mx/i),my/(my/i)); ans+=trunc(my/(i*k))*trunc(mx/(i*k))*(mu[j]-mu[i-1]); i=j+1; } return (int)ans; }int main(){ freopen("inversion.in","r",stdin); getprime(50000); scanf("%d",&n); mu[1]=1; int i; fo(i,2,50000) mu[i]+=mu[i-1]; while(n-->0) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("%d\n",(int)(find(k,b,d)-find(k,a-1,d)-find(k,b,c-1)+find(k,a-1,c-1))); }}
- 莫比乌斯反演之入门
- 莫比乌斯反演(入门)
- 莫比乌斯反演入门
- 莫比乌斯反演入门
- 莫比乌斯反演入门
- 莫比乌斯反演入门(详解)
- 莫比乌斯反演入门
- 莫比乌斯反演入门
- 【莫比乌斯反演】莫比乌斯反演入门及推导
- 【莫比乌斯反演】莫比乌斯反演入门及推导
- 二项式反演,莫比乌斯反演。
- HDU 1695 GCD(莫比乌斯反演,入门)
- hdu 1695 莫比乌斯反演入门题
- [kuangbin]莫比乌斯反演——入门
- 莫比乌斯反演入门及推导
- 莫比乌斯反演入门「转载」
- hdu 1695 GCD(莫比乌斯反演入门)
- 莫比乌斯反演
- leetcode uglynumber
- Linux基础(一)——文件基本属性
- 高效使用你的Xcode
- BZOJ2851: 极限满月
- 关于std数组和内置数组初始化的疑惑
- 莫比乌斯反演入门
- 关于 ThreadLocal
- leetcode 239. Sliding Window Maximum
- 软件设计七大原则
- 第15周程序阅读3
- 彻底解决 libhdf5_hl.so.10: cannot open shared object file: No such file or directory
- JZOJ.3432【GDOI2014模拟】服务器 解题报告
- 图的遍历算法-马遍历棋盘
- 数字三角形问题