2019.01.21【洛谷P5176】公约数(莫比乌斯反演)(Min-Max容斥推结论)

传送门


BB:

zxyoi做这道题的心路历程大概是这样子的:

闲来无事题库乱逛,一搜”约数“出来一道黑题。

然后随手就点开了。

一看这个式子。。。我。。。

好的肯定是要化成两两的 g c d gcd gcd不然没法做。

日,这个怎么化。。。

这个 g c d ( i , j , k ) gcd(i,j,k) gcd(i,j,k)是要干什么?

这个 g c d ( i j , j k , i k ) gcd(ij,jk,ik) gcd(ij,jk,ik)又是什么东西?好像可以用质因数分解来搞一搞。

然后就做出来了。日,这有黑题难度?

一发A了,一看全NM开O2跑得贼快。不行我也要开O2。

然后就洛谷Rank1了。。。

思路:

最难受的就是那个 g c d ( i j , j k , i k ) gcd(ij,jk,ik) gcd(ij,jk,ik),所以我们想办法把它给化简。

由于 g c d gcd gcd有一种表示方式是酱紫的:

a = ∏ p i a i , b = ∏ p i b i a=\prod p_i^{a_i},b=\prod p_i^{b_i} a=piai,b=pibi

g c d ( a , b ) = ∏ p i min ⁡ ( a i , b i ) gcd(a,b)=\prod p_i^{\min(a_i,b_i)} gcd(a,b)=pimin(ai,bi)

所以我们考虑分别每个质因子在 i , j , k i,j,k i,j,k中出现的次数,记为 I , J , K I,J,K I,J,K

假设现在考虑且仅考虑质因子 p p p
现在我们考虑给 g c d gcd gcd换一种表示方式,记录当前质因子的次数。

大概就是这么个意思:
g c d ( i , j ) = min ⁡ ( I , J ) g c d ( j , k ) = min ⁡ ( J , K ) g c d ( i , k ) = min ⁡ ( I , K ) g c d ( i , j , k ) = min ⁡ ( I , J , K ) g c d ( i j , i k , j k ) = min ⁡ ( I + J , J + K , I + K ) \begin{aligned} gcd(i,j)&=\min(I,J)\\ gcd(j,k)&=\min(J,K)\\ gcd(i,k)&=\min(I,K)\\ gcd(i,j,k)&=\min(I,J,K)\\ gcd(ij,ik,jk)&=\min(I+J,J+K,I+K) \end{aligned} gcd(i,j)gcd(j,k)gcd(i,k)gcd(i,j,k)gcd(ij,ik,jk)=min(I,J)=min(J,K)=min(I,K)=min(I,J,K)=min(I+J,J+K,I+K)

所以 g c d ( i j , i k , j k ) gcd(ij,ik,jk) gcd(ij,ik,jk)就是选择了 I , J , K I,J,K I,J,K三者中较小的两个。

容斥一下可以得到(本质是 M i n − M a x Min-Max MinMax容斥): min ⁡ ( I + J , J + K , I + K ) = min ⁡ ( I , J ) + min ⁡ ( J , K ) + min ⁡ ( I , K ) − min ⁡ ( I , J , K ) \min(I+J,J+K,I+K)=\min(I,J)+\min(J,K)+\min(I,K)-\min(I,J,K) min(I+J,J+K,I+K)=min(I,J)+min(J,K)+min(I,K)min(I,J,K)

很简单的容斥,就是说,在前三项中,次小值会出现一次,最小值会出现两次,最后一项会删掉重复出现的最小值,所以两边是相等的。

换回 g c d gcd gcd的表达式的话就是这个:
g c d ( i j , i k , j k ) = g c d ( i , j ) g c d ( i , k ) g c d ( j , k ) g c d ( i , j , k ) gcd(ij,ik,jk)=\frac{gcd(i,j)gcd(i,k)gcd(j,k)}{gcd(i,j,k)} gcd(ij,ik,jk)=gcd(i,j,k)gcd(i,j)gcd(i,k)gcd(j,k)

代回去得到我们真正要求的东西:
A n s = ∑ i = 1 n ∑ j = 1 m ∑ k = 1 p g c d ( i , j ) 2 + g c d ( i , k ) 2 + g c d ( j , k ) 2 Ans=\sum_{i=1}^n\sum_{j=1}^m\sum_{k=1}^{p}gcd(i,j)^2+gcd(i,k)^2+gcd(j,k)^2 Ans=i=1nj=1mk=1pgcd(i,j)2+gcd(i,k)2+gcd(j,k)2

然后,zxyoi当场就来了一句 w o c woc woc,这不就是基础莫比乌斯反演题了吗?

考虑将询问拆分一下: A n s = p ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) 2 + n ∑ j = 1 m ∑ k = 1 p g c d ( j , k ) 2 + m ∑ i = 1 n ∑ k = 1 p g c d ( i , k ) 2 Ans=p\sum_{i=1}^{n}\sum_{j=1}^mgcd(i,j)^2+n\sum_{j=1}^m\sum_{k=1}^pgcd(j,k)^2+m\sum_{i=1}^n\sum_{k=1}^pgcd(i,k)^2 Ans=pi=1nj=1mgcd(i,j)2+nj=1mk=1pgcd(j,k)2+mi=1nk=1pgcd(i,k)2

现在考虑怎么处理这个东西:

∑ i = 1 n ∑ j = 1 m g c d ( i , j ) 2 \begin{aligned} \sum_{i=1}^n\sum_{j=1}^mgcd(i,j)^2 \end{aligned} i=1nj=1mgcd(i,j)2

接下来是莫比乌斯反演的时间:
A n s = ∑ d = 1 min ⁡ ( n , m ) d 2 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] = ∑ d = 1 min ⁡ ( n , m ) d 2 ∑ i = 1 n ∑ j = 1 m ∑ t ∣ g c d ( i , j ) μ ( t ) = ∑ d = 1 min ⁡ ( n , m ) d 2 ∑ t = 1 ⌊ min ⁡ ( n , m ) d ⌋ ⌊ n d t ⌋ ⌊ m d t ⌋ = ∑ T = 1 min ⁡ ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T d 2 μ ( T d ) \begin{aligned} Ans=&\sum_{d=1}^{\min(n,m)}d^2\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=d]\\ =&\sum_{d=1}^{\min(n,m)}d^2\sum_{i=1}^n\sum_{j=1}^{m}\sum_{t\mid gcd(i,j)}\mu(t)\\ =&\sum_{d=1}^{\min(n,m)}d^2\sum_{t=1}^{\lfloor\frac{\min(n,m)}{d}\rfloor}\lfloor\frac{n}{dt}\rfloor\lfloor\frac{m}{dt}\rfloor\\ =&\sum_{T=1}^{\min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d\mid T}d^2\mu(\frac{T}d) \end{aligned} Ans====d=1min(n,m)d2i=1nj=1m[gcd(i,j)=d]d=1min(n,m)d2i=1nj=1mtgcd(i,j)μ(t)d=1min(n,m)d2t=1dmin(n,m)dtndtmT=1min(n,m)TnTmdTd2μ(dT)

g ( T ) = ∑ d ∣ T d 2 μ ( T d ) g(T)=\sum_{d\mid T}d^2\mu(\frac{T}d) g(T)=dTd2μ(dT)

很显然 g g g是个积性函数,因为 g = I d 2 ∗ μ g=Id^2*\mu g=Id2μ

那么考虑线性筛。

g ( 1 ) = 1 g(1)=1 g(1)=1

∀ p ∈ P , g ( p ) = p 2 − 1 \forall p\in \mathbb P,g(p)=p^2-1 pP,g(p)=p21

∀ p ∈ P , n ∈ N ∗ , g c d ( n , p ) = 1 , g ( n p ) = g ( n ) g ( p ) \forall p\in \mathbb P,n\in \mathbb N_*,gcd(n,p)=1,g(np)=g(n)g(p) pP,nN,gcd(n,p)=1,g(np)=g(n)g(p)

∀ p ∈ P , n ∈ N ∗ , p ∣ n , g ( n p ) = p 2 g ( n ) \forall p\in \mathbb P,n\in \mathbb N_*,p\mid n,g(np)=p^2g(n) pP,nN,pn,g(np)=p2g(n)

最后一个稍微考虑一下有哪些数会产生新的贡献大概就明白了。

总的来说感觉不够当一道黑题,顶多紫题。


代码:

#include
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc putchar
#define cs const

namespace IO{
	namespace IOONLY{
		cs int Rlen=1<<16|1;
		char buf[Rlen],*p1,*p2;
	}
	inline char get_char(){
		using namespace IOONLY;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re int num;
		re char c;
		while(!isdigit(c=gc()));num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

cs int P=20000007,N=P-7;
cs int mod=1000000007;

inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int mul(int a,int b){return (ll)a*b>=mod?(ll)a*b%mod:(ll)a*b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}

int prime[P],pcnt;
int g[P];
bool mark[P];
inline void linear_sieves(int len=N){
	g[1]=1;
	for(int re i=2;i<=len;++i){
		if(!mark[i])prime[++pcnt]=i,g[i]=dec(mul(i,i),1);
		for(int re j=1;i*prime[j]<=len;++j){
			mark[i*prime[j]]=true;
			if(i%prime[j]==0){
				g[i*prime[j]]=mul(mul(prime[j],prime[j]),g[i]);
				break;
			}
			g[i*prime[j]]=mul(g[i],g[prime[j]]);
		}
	}
	for(int re i=2;i<=len;++i)g[i]=add(g[i],g[i-1]);
}

inline int calc(int n,int m){
	int ans=0;
	if(n>m)swap(n,m);
	for(int re i=1,j;i<=n;i=j+1){
		j=min(n/(n/i),m/(m/i));
		ans=add(ans,mul(mul(n/i,m/i),dec(g[j],g[i-1])));
	}
	return ans;
}

inline int solve(int n,int m,int p){
	return add(add(mul(p,calc(n,m)),mul(n,calc(p,m))),mul(m,calc(n,p)));
}

signed main(){
	linear_sieves();
	for(int re T=getint();T--;cout<<solve(getint(),getint(),getint())<<'\n');
	return 0;
}

你可能感兴趣的:(容斥原理,莫比乌斯反演)