#莫比乌斯反演,杜教筛#洛谷 6055 [RC-02] GCD

题目


分析

如果令 \(u=pj,v=qj\) ,那么本质上就是让 \(gcd(i,u,v)==1\)

那就是 \(\sum_{i=1}^n\sum_{u=1}^n\sum_{v=1}^n[gcd(i,u,v)==1]\)

莫比乌斯反演就可以得到 \(\sum_{T=1}^n\mu(T)\left(\left\lfloor\frac{n}{T}\right\rfloor\right)^3\)

这个杜教筛就可以了


代码

#include <cstdio>
#include <unordered_map>
#define rr register
using namespace std;
const int N=10000011,mod=998244353;
unordered_map<int,int>uk;
int prime[N],v[N],mu[N],n,Cnt,ans;
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline void Pro(int n){
	mu[1]=1;
	for (rr int i=2;i<=n;++i){
		if (!v[i]) prime[++Cnt]=v[i]=i,mu[i]=mod-1;
		for (rr int j=1;j<=Cnt&&prime[j]<=n/i;++j){
			v[i*prime[j]]=prime[j];
			if (i%prime[j]==0) break;
			mu[i*prime[j]]=mod-mu[i]; 
		}
	}
	for (rr int i=2;i<=n;++i) mu[i]=mo(mu[i-1],mu[i]);
}
inline signed Smu(int n){
	if (n<=N-11) return mu[n];
	if (uk[n]) return uk[n];
	rr int ans=0;
	for (rr int l=2,r;l<=n;l=r+1)
		r=n/(n/l),ans=mo(ans,1ll*(r-l+1)*Smu(n/l)%mod);
    return uk[n]=mo(mod-ans,1);
}
signed main(){
	Pro(N-11),scanf("%d",&n);
	for (rr int l=1,r;l<=n;l=r+1){
		rr int t=1ll*(n/l)*(n/l)%mod*(n/l)%mod;
		r=n/(n/l),ans=mo(ans,1ll*mo(Smu(r),mod-Smu(l-1))*t%mod);
	}
	return !printf("%d",ans);
}
posted @ 2021-12-21 19:18  lemondinosaur  阅读(22)  评论(0编辑  收藏  举报