卷积与莫比乌斯反演
目录
卷积与莫比乌斯反演
0前言
0.1前置技能
0.2问题的引入
1.简单定义
1.1数论函数的定义
1.2卷积的定义
1.3反演的基本形式
2.1莫比乌斯反演
3.1例题:【luogu-P2257 YY的GCD】
题目大意:
solution1
solution2
0.前言
莫比乌斯反演是数论数学中很重要的内容,可以用于解决很多组合数学的问题。
来源——百度百科
0.1前置技能
- 初一数学水平。
- 对卷积、莫比乌斯函数有简单了解。
0.2问题的引入
OI竞赛中,经常遇到这样一类数学问题:
显然,暴力的时间复杂度是的,显然这个复杂度是我们无法接受的。
然而,倘若我们使用莫比乌斯反演,就能够大大优化其时间复杂度。
1.简单定义
1.1数论函数的定义
若函数是正整数域内的函数,则称为数论函数。
对于一个数论函数,对于任意互质的正整数,满足,则称 是积性函数。
对于一个数论函数,对于任意的正整数,满足,则称 是完全积性函数。
1.2卷积的定义
有两个数论函数,则他们的卷积:
易得:若两个数论函数是积性的,那么卷积 也是积性的。
设
有以下一些常用的函数:
- 元函数:
- 恒等函数:
- 单位函数:
- 欧拉函数: 表示 中与n互质的数的个数。
- 莫比乌斯函数:
- 约数和函数: 表示n的正约数和。
- 约数个数函数: 表示n的正约数个数。 ‘
容易发现如下性质:
- 对于任意数论函数 这是莫比乌斯反演的核心公式。
- 对于任意数论函数。
1.3容斥
我们定义一个函数,再通过定义函数,使得:
我们可以从 函数的值 反推出函数的值。
倘若我们能快速计算函数的值,那么就可以求得 。
事实上,这与反演的思想有异曲同工之妙。
2.1莫比乌斯反演
在莫比乌斯反演中,我们需要快速求出:
因此
除此之外,还有
在能够快速求得函数的情况下,我们就可以很容易地得出函数的值。
这就是莫比乌斯反演了。
3.1例题:【luogu-P2257 YY的GCD】
题目大意:
给定。
求且 为质数的 有多少对。
solution1
这一个简单的不使用反演的解法。(事实上就是写出了反演省略的步骤)
显然:
把K提出来:
设
直接数论分块即可。
solution2
这是一个运用反演知识的解法。
设 表示满足 且 的 的对数。
设 表示满足 且 的 的对数。
那么:
且
使用莫比乌斯反演,即得:
便可以得到solution1中的式子,直接数论分块做。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e7+50;
int pnum=0;
bool vis[MAXN];
ll mu[MAXN],Prime[MAXN],sum[MAXN],g[MAXN];
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }return x*f;
}
void init(int n)
{vis[1]=mu[1]=1;for (int i=2;i<=n;i++){if (!vis[i]) { mu[i]=-1; Prime[++pnum]=i; }for (int j=1;j<=pnum&&Prime[j]*i<=n;j++){vis[Prime[j]*i]=1;if (!(i%Prime[j])) break;mu[Prime[j]*i]=-mu[i];}}for (int i=1;i<=n;i++)for (int j=1;j<=pnum&&Prime[j]*i<=n;j++) g[Prime[j]*i]+=mu[i]; for (int i=1;i<=n;i++) sum[i]=sum[i-1]+g[i];
}
int main()
{init(1e7);int Case=read();while (Case--){ll n=read(),m=read(),ans=0;if (n>m) swap(n,m);for (ll l=1,r;l<=n;l=r+1){r=min(n/(n/l),m/(m/l));ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);} printf("%lld\n",ans);}return 0;
}
时间复杂度大概是 。