LOJ #2185 / 洛谷 P3329 - [SDOI2015]约数个数和(莫比乌斯函数)

LOJ 题面传送门 / 洛谷题面传送门

题意:

  • \(\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\)\(d(x)\)\(x\) 的约数个数。
  • \(n,m \leq 5 \times 10^4\)

抛出一个引理:\(d(ij)=\sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y)=1]\),该定理将在这篇博客结束证明。
知道这个定理之后,就可以按照套路开始推式子了:

\[\begin{aligned}&ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\\&=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y)=1]\\&=\sum\limits_{x=1}^n\sum\limits_{y=1}^m\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{y}\rfloor\times[\gcd(x,y)=1]\\&=\sum\limits_{x=1}^n\sum\limits_{y=1}^m\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{y}\rfloor\times\sum\limits_{p|\gcd(x,y)}\mu(p)\\&=\sum\limits_{p=1}^{\min(n,m)}\mu(p)\times\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}\lfloor\frac{n}{ip}\rfloor\lfloor\frac{m}{jp}\rfloor\\&=\sum\limits_{p=1}^{\min(n,m)}\mu(p)\times\sum\limits_{i=1}^{\lfloor\frac{n}{p}\rfloor}\lfloor\frac{n}{ip}\rfloor\times\sum\limits_{j=1}^{\lfloor\frac{m}{p}\rfloor}\lfloor\frac{m}{jp}\rfloor\end{aligned} \]

\(t(x)=\sum\limits_{i=1}^x\lfloor\frac{x}{i}\rfloor\),则原式进一步转化为 \(\sum\limits_{p=1}^{\min(n,m)}\mu(p)\times t(\lfloor\frac{n}{p}\rfloor)\times t(\lfloor\frac{m}{p}\rfloor)\)
整除分块预处理出 \(t(x)\),这样可以 \(\mathcal O(1)\) 求出 \(\sum\) 里面那堆东西。外面再套个整除分块就可以过了。时间复杂度 \(\mathcal O(T\sqrt{n}+n\sqrt{n})\)


最后再证明一下 \(d(ij)=\sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y)=1]\)
假设 \(i,j\) 总共含有 \(p_1,p_2,\dots,p_k\)\(k\) 个质因子,\(ij\) 有一个因子 \(c\)
我们需证明每个 \(c\) 与一个互质数对 \((a,b)\ \ (a|i,b|j)\) 一一对应。
对于质因子 \(p_t\),假设 \(i\) 中包含 \(p_t^{x_1}\)\(j\) 中包含 \(p_t^{x_2}\)\(c\) 中包含 \(p_t^{x_3}\),显然 \(x_3 \leq x_1+x_2\)
如果 \(x_3 \leq x_1\),那么我们就在 \(a\) 中分配 \(p_t^{x_3}\)
如果 \(x_3 > x_1\),那么我们就在 \(b\) 中分配 \(p_t^{x_3-x_1}\)
显然 \(a,b\) 中最多一个包含质因子 \(p_t\),故 \(\gcd(a,b)=1\)。而每个 \(p_t\) 的分配方式又对应着一个 \(c\),故每个 \(c\) 与一个互质数对 \((a,b)\ \ (a|i,b|j)\) 一一对应,原命题得证。

/*
Contest: - 
Problem: P3327 
Author: tzc_wk
Time: 2020.9.1 
*/
#include <bits/stdc++.h>
using namespace std;
#define fi			first
#define se			second
#define pb			push_back
#define fz(i,a,b)	for(int i=a;i<=b;i++)
#define fd(i,a,b)	for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a)		a.begin(),a.end()
#define fill0(a)	memset(a,0,sizeof(a))
#define fill1(a)	memset(a,-1,sizeof(a))
#define fillbig(a)	memset(a,0x3f,sizeof(a))
#define y1			y1010101010101
#define y0			y0101010101010
typedef pair<int,int> pii;
typedef long long ll;
inline int read(){
	int x=0,neg=1;char c=getchar();
	while(!isdigit(c)){
		if(c=='-') neg=-1;
		c=getchar();
	}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x*neg;
}
bool vis[50005];
ll mu[50005],pri[50005],sum[50005],pcnt=0;
inline void get_mu(){
	mu[1]=1;
	for(int i=2;i<=50000;i++){
		if(!vis[i]){mu[i]=-1;pri[++pcnt]=i;}
		for(int j=1;j<=pcnt&&pri[j]*i<=50000;j++){
			vis[i*pri[j]]=1;
			if(i%pri[j]==0) break;
			else mu[pri[j]*i]=-mu[i];
		}
	}
	for(int i=1;i<=50000;i++) sum[i]=sum[i-1]+mu[i];
}
inline ll calc(int x){
	ll ans=0;for(int l=1,r;l<=x;l=r+1){
		r=x/(x/l);
		ans+=1ll*(r-l+1)*(x/l);
	}
	return ans;
}
int t[50005];
int main(){
	get_mu();fz(i,1,50000) t[i]=calc(i);
	int T=read();while(T--){
		int n=read(),m=read();ll ans=0;
		if(n>m) n^=m^=n^=m;
		for(int l=1,r;l<=n;l=r+1){
			r=min(n/(n/l),m/(m/l));
			ans+=(sum[r]-sum[l-1])*t[n/l]*t[m/l];
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2020-09-01 21:41  tzc_wk  阅读(142)  评论(0)    收藏  举报