LOJ6181 某个套路求和题

某个套路求和题

从前有个 alpha1022,他在看某本奇妙的书的时候想到了这样一个函数:

\[f(n) = \prod_{d|n} \mu(d) \]

然后就有了这样一个问题:

\[\sum_{i=1}^n f(i) \mod 998244353 \]

然后他就把这个问题扔给了你。

对于 \(100\%\) 的数据,\(n \le 10^{10}\)

题解

http://jklover.hs-blog.cf/2020/04/19/Loj-6181-某个套路求和题/

考虑化简\(f(n)=\prod_{d|n} \mu(d)\)

\(n\)有平方因子时,\(f(n) = 0\),否则我们考虑有几个\(\mu(d)=-1\),就可以算出\(\mu(n)\)

\(n\)\(\omega(n)\)种不同的质因子,由于\(n\)没有平方因子,所以各个质因子的次数都是\(1\)

\(d\)\(n\)的约数可以看做从\(\omega(n)\)个质因子中选出一些乘起来组成的,而\(\mu(d)=-1\)等价于选了奇数个。

那么显然有\(2^{\omega(n)-1}\)种选法,只有当\(n\)为质数时有奇数个\(\mu(d)=-1\),其他情况都有偶数个。

于是可以得出

\[\text{ans}=\sum_{i=1}^n\mu^2(i) -\sum_{i=1}^n 2\times [i\in P] \]

后者是\(1\)\(n\)中质数个数的\(2\)倍,可以用Min_25筛求出.

考虑如何求\(\sum \mu^2(i)\),记\(p(n)=\max_{d^2|n} \lbrace d\rbrace\)表示\(n\)的最大平方因子,则

\[\sum_{i=1}^n \mu^2(i) \\ =\sum_{i=1}^n [p(i)=1] \\ =\sum_{d=1}^n \mu(d) \sum_{d|p(i)}1 \\ =\sum_{d=1}^n\mu(d) \sum_{d^2|i} 1\\ =\sum_{d=1}^n \mu(d) \lfloor \frac n {d^2} \rfloor \]

于是筛出\(\sqrt n\)以内的\(\mu\),就可以在\(O(\sqrt n)\)内计算出\(\sum \mu^2(i)\)了。

CO int N=2e5+10,mod=998244353;
int prime[N],num,mu[N];
int pos[N],idx,ref1[N],ref2[N],H[N];

signed main(){
	int n=read<int>(),m=ceil(sqrt(n));
	mu[1]=1;
	for(int i=2;i<=m;++i){
		if(!prime[i]) prime[++num]=i,mu[i]=-1;
		for(int j=1;j<=num and i*prime[j]<=m;++j){
			prime[i*prime[j]]=1;
			if(i%prime[j]==0) break;
			mu[i*prime[j]]=-mu[i];
		}
	}
	for(int l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		pos[++idx]=n/l;
		if(n/l<=m) ref1[n/l]=idx;
		else ref2[n/(n/l)]=idx;
	}
	for(int i=1;i<=idx;++i) H[i]=pos[i]-1;
	for(int j=1;j<=num;++j)
		for(int i=1;i<=idx and prime[j]*prime[j]<=pos[i];++i){
			int k=pos[i]/prime[j];
			if(k<=m) k=ref1[k];
			else k=ref2[n/k];
			H[i]-=H[k]-(j-1);
		}
	int ans=0;
	for(int i=1;i*i<=n;++i) ans+=mu[i]*(n/(i*i));
	ans-=2*H[1];
	printf("%lld\n",(ans%mod+mod)%mod);
	return 0;
}

posted on 2020-04-25 22:00  autoint  阅读(326)  评论(0编辑  收藏  举报

导航