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;
}
静渊以有谋,疏通而知事。