蒟蒻TJY的博客

[莫比乌斯反演][min_25筛]任凭风浪起,稳坐钓鱼台(续)

Description

\[\sum_{j=1}^n\sum_{k=1}^n\mu(j k)\pmod{2^{32}} \]

其中\(n\le10^9.\)

Solution

首先是莫比乌斯反演经典套路。

\[\begin{align*} \sum_{j=1}^n\sum_{k=1}^n\mu(j k)&=\sum_{j=1}^n\sum_{k=1}^n\mu(j)\mu(k)[\gcd(j,k)=1]\\ &=\sum_{j=1}^n\sum_{k=1}^n\mu(j)\mu(k)\sum_{d|j,d|k}\mu(d)\\ &=\sum_{d=1}^n\mu(d)\sum_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(j d)\sum_{k=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(k d)\\ &=\sum_{d=1}^n\mu(d)\sum_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(j)[\gcd(j,d)=1]\sum_{k=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(k)[\gcd(k,d)=1] \end{align*} \]

我们记

\[f(n,a)=\sum_{k=1}^n\mu(k)[\gcd(k,a)=1] \]

那么就有

\[\sum_{j=1}^n\sum_{k=1}^n\mu(j k)=\sum_{d=1}^n\mu(d)f\left(\left\lfloor\frac{n}{d}\right\rfloor,d\right)^2 \]

哪怕不考虑求\(f\)的开销,这也是\(O(n)\),必须进行优化。

观察到当\(d\)很大时,\(\left\lfloor\frac{n}{d}\right\rfloor\)很小,不妨设一个阈值\(B\),和端点\(L=\left\lfloor\frac{n}{B+1}\right\rfloor\)

\[\begin{align*} \sum_{j=1}^n\sum_{k=1}^n\mu(j k)&=\sum_{d=1}^B\mu(d)f\left(\left\lfloor\frac{n}{d}\right\rfloor,d\right)^2+\sum_{B+1}^n\mu(d)\sum_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(j)[\gcd(j,d)=1]\sum_{k=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\mu(k)[\gcd(k,d)=1]\\ &=\sum_{d=1}^B\mu(d)f\left(\left\lfloor\frac{n}{d}\right\rfloor,d\right)^2+\sum_{j=1}^L\sum_{k=1}^L\mu(j)\mu(k)\sum_{i=B+1}^{\min{\{n/j,n/k\}}}\mu(i)[\gcd(i,j)=1][\gcd(i,k)=1]\\ &=\sum_{d=1}^B\mu(d)f\left(\left\lfloor\frac{n}{d}\right\rfloor,d\right)^2+2\sum_{j=1}^L\sum_{k=1}^{j-1}\mu(j)\mu(k)\sum_{i=B+1}^{\left\lfloor\frac{n}{j}\right\rfloor}\mu(i)[\gcd(i,jk)=1]\\ &\qquad\qquad\qquad\qquad\qquad\qquad\qquad+\sum_{j=1}^L\mu(j)^2\sum_{i=B+1}^{\left\lfloor\frac{n}{j}\right\rfloor}\mu(i)[\gcd(i,j)=1] \\ &=\sum_{d=1}^B\mu(d)f\left(\left\lfloor\frac{n}{d}\right\rfloor,d\right)^2+2\sum_{j=1}^L\sum_{k=1}^{j-1}\mu(j)\mu(k)\left(f\left(\left\lfloor\frac{n}{d}\right\rfloor,jk\right)-f(B,jk)\right)\\ &\qquad\qquad\qquad\qquad\qquad\qquad\qquad+\sum_{j=1}^L\mu(j)^2\left(f\left(\left\lfloor\frac{n}{d}\right\rfloor,j\right)-f(B,j)\right) \end{align*} \]

总时间复杂度(不考虑\(f\))为\(O(B+\left(\frac{n}{B}\right)^2)\),显然当\(B=n^\frac{2}{3}\)时取到最小值,为\(O(n^\frac{2}{3}).\)

那么问题就变成如何快速地求出\(f(n,a).\)

\[\begin{align*} f(n,a)&=\sum_{k=1}^n\mu(k)[\gcd(k,a)=1]\\ &=\sum_{k=1}^n\mu(k)\sum_{t|k,t|a}\mu(t)\\ &=\sum_{t|a}\mu(t)\sum_{k=1}^{\left\lfloor\frac{n}{t}\right\rfloor}\mu(k t)\\ &=\sum_{t|a}\mu(t)^2\sum_{k=1}^{\left\lfloor\frac{n}{t}\right\rfloor}\mu(k)[\gcd(k,t)=1]\\ &=\sum_{t|a}\mu(t)^2f\left(\left\lfloor\frac{n}{t}\right\rfloor,t\right) \end{align*} \]

用这个递推式就可以比较快速地计算\(f\)了。

对于边界:\(f(n,1)\),就是\(\mu\)的前缀和,用min_25筛预处理出整除分块得出的所有\(2\sqrt{n}\)个位置的前缀和。

(原因:\(\left\lfloor\frac{\left\lfloor\frac{n}{a}\right\rfloor}{b}\right\rfloor=\left\lfloor\frac{n}{a b}\right\rfloor\)

同时,我们可以在\(O(A \log A)\)的时间内预处理出所有\(n a\le A\)\(f(n,a)\),以卡常。

至此,问题解决。总复杂度是亚线性的。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e9+1,M=1e6+1;
int n,b,l,cnt,pri[M],frm[M];
bool cm[M];
uint ans,mu[M],mt[1<<8];
vector<uint> pre[M];
inline uint sqr(uint x){return x*x;}
void sieve(){
	mu[1]=1;
	for(int i=2;i<M;i++){
		if(!cm[i]){pri[++cnt]=i;frm[i]=i;mu[i]=-1;}
		for(int j=1;j<=cnt&&i*pri[j]<M;j++){
			cm[i*pri[j]]=true;
			frm[i*pri[j]]=pri[j];
			if(i%pri[j])mu[i*pri[j]]=-mu[i];
			else break;
		}
	}
}
namespace min_25{
	int m,w[M],id1[M],id2[M];
	uint g[M],s[M];
	inline int id(int x){
		if(x<M)return id1[x];
		else return id2[n/x];
	}
	void work(){
		for(int l=1,r;l<=n;l=r+1){
			r=n/(n/l);
			w[++m]=n/l;
			g[m]=-w[m]+1;
			if(w[m]<M)id1[w[m]]=m;
			else id2[r]=m;
		}
		for(int j=1;j<=cnt;j++){
			for(int i=1;i<=m&&(ll)pri[j]*pri[j]<=w[i];i++){
				int k=id(w[i]/pri[j]);
				g[i]-=g[k]+j-1;
			}
		}
		for(int i=1;i<=m;i++)s[i]=g[i];
		for(int j=cnt;j>=1;j--)for(int i=1;i<=m&&(ll)pri[j]*pri[j]<=w[i];i++)s[i]-=s[id(w[i]/pri[j])]+j;
	}
	inline uint smu(int x){return s[id(x)]+1;}
}
void init(){
	for(int i=1;i<M;i++)pre[i].resize((M-1)/i+1);
	pre[1][0]=1;
	for(int i=1;i<M;i++)for(int j=1;j<=(M-1)/i;j++)pre[i][j]=(i<=j?pre[i][j-i]:pre[j][i]);
	for(int i=1;i<M;i++)for(int j=0;j<=(M-1)/i;j++)pre[i][j]=pre[i][j-1]+mu[j]*pre[i][j];
}
uint f(int n,int a){
	if((ll)a*n<=(M-1))return pre[a][n];
	if(n==1||a==1)return min_25::smu(n);
	vector<int>sum;
	while(a!=1){
		int p=frm[a];
		sum.push_back(p);
		while(a%p==0)a/=p;
	}
	int sz=sum.size();
	mt[0]=1;
	uint ans=min_25::smu(n);
	for(int i=1;i<(1<<sz);i++){
		int x=i&(-i);
		mt[i]=mt[i^x]*sum[__builtin_ctz(i)];
		ans+=f(n/mt[i],mt[i]);
	}
	return ans;
}
int main(){
	sieve();
	scanf("%d",&n);
	min_25::work();
	init();
	b=n/(n/min(n,1000000)+1);
	l=n/(b+1);
	for(int i=1;i<=b;i++)if(mu[i])ans+=mu[i]*sqr(f(n/i,i));
	for(int i=1;i<=l;i++)for(int j=1;j<i;j++)if(mu[i]&&mu[j])ans+=2*mu[i]*mu[j]*(f(n/i,i*j)-f(b,i*j));
	for(int i=1;i<=l;i++)if(mu[i])ans+=sqr(mu[i])*(f(n/i,i)-f(b,i));
	printf("%u\n",ans);
}
posted @ 2020-11-17 21:01  蒟蒻TJY  阅读(154)  评论(2编辑  收藏  举报