把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【洛谷4450】双亲数(莫比乌斯反演大水题)

点此看题面

大致题意:\(\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)==d]\)

前言

前一天在比赛中遇到一道莫比乌斯反演题,结果因为太久没做有些生疏,就没做出来。

今天决定找道莫比乌斯反演题补一补。

因此,虽然这道题目很水,而且看起来很眼熟,似乎曾经做过类似的题目,但我依然试着去写了写。

莫比乌斯反演

考虑将式子中的\(i,j\)同时除以\(d\),就可以得到:

\[\sum_{i=1}^{\lfloor\frac nd\rfloor}\sum_{j=1}^{\lfloor\frac md\rfloor}[gcd(i,j)==1] \]

按照套路,由于\(\sum_{p|x}\mu(p)=[x==1]\),所以我们可以把\([gcd(i,j)==1]\)转化,便得到:

\[\sum_{i=1}^{\lfloor\frac nd\rfloor}\sum_{j=1}^{\lfloor\frac md\rfloor}\sum_{p|i,p|j}\mu(p) \]

枚举\(p\),就可以得到:

\[\sum_{p=1}^{min(\lfloor\frac nd\rfloor,\lfloor\frac md\rfloor)}\mu(p)\lfloor\frac n{dp}\rfloor\lfloor\frac m{dp}\rfloor \]

其中,不难发现每次\(n\)\(m\)出现都伴随着一个除以\(d\),因此我们可以在读入之后直接把\(n,m\)各自除以\(d\),然后便可以得到一个更为简洁的式子:

\[\sum_{p=1}^{min(n,m)}\mu(p)\lfloor\frac n{p}\rfloor\lfloor\frac m{p}\rfloor \]

考虑到求预处理\(\mu\)的过程本身就是\(O(n)\)的,因此这里我们完全可以直接枚举\(p\)

但正如前言中所说,做这道题是为了重拾莫比乌斯反演,所以我义无反顾地去写了个除法分块。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define LL long long
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int n,m,d;
class LinearSieve//线性筛筛μ
{
	private:
		int Pt,P[N+5],mu[N+5];
	public:
		I int operator [] (CI x) {return mu[x];}
		I LinearSieve()
		{
			RI i,j;for(mu[1]=1,i=2;i<=N;++i)
				for(!P[i]&&(mu[P[++Pt]=i]=-1),j=1;j<=Pt&&i*P[j]<=N;++j)
					if(P[i*P[j]]=1,i%P[j]) mu[i*P[j]]=-mu[i];else break;
			for(i=2;i<=N;++i) mu[i]+=mu[i-1];//统计前缀和
		}
}Mu;
int main()
{
	RI l,r,lim;LL t=0;scanf("%d%d%d",&n,&m,&d),n/=d,m/=d;//一开始直接各除以d
	for(lim=min(n,m),l=1;l<=lim;l=r+1)//除法分块
		r=min(n/(n/l),m/(m/l)),t+=1LL*(Mu[r]-Mu[l-1])*(n/l)*(m/l);
	return printf("%lld",t),0;//输出答案
}
posted @ 2019-12-22 10:38  TheLostWeak  阅读(189)  评论(0编辑  收藏  举报