Description
求
∑i=1n2f(i)
f(i)表示i的不同的质因子个数
n<=10^12
Solution
我们设g(i)=2^f(i),显然g是积性函数
那么我们可以尝试杜教筛g
把g卷上一个mu,设g*mu=h
显然h也是积性函数
分析一下h(p^k),我们可以发现h(p^k)=[k==1]
特别的h[1]=1
那么归纳一下我们可以发现h=mu^2!!
也就是g*mu=mu^2
两边再卷上一个I,那么g=mu^2*I
说人话就是g(n)=∑d|nmu(i)2
这样是可以杜教筛的,但是由于出题人很不良心这样会被卡成暴力分
我们需要一个更优秀的解法
先把原式子写出来
Ans=∑i=1n∑d|iμ(d)2
枚举j=i/d,
Ans=∑j=1n∑d=1⌊nj2⌋μ(d)2
考虑∑ni=1μ(d)2要怎么求
如果存在一个p^2|d那么mu(d)^2=0否则mu(d)^2=1
如果我们考虑容斥,枚举一个p^2把答案减去n/(p^2)
但这样会算重所有我们要加上n/(p*p’)^2
可以发现容斥系数相当于mu
所以
∑i=1nμ(d)2=∑i=1n√μ(i)⌊ni2⌋
Ans=∑j=1n∑d=1⌊nj2⌋μ(d)⌊nd2j⌋
Ans=∑d=1n√μ(d)∑j=1⌊nd2⌋⌊nd2j⌋
后面可以分块,复杂度O(n√logn13)
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int N=1e6+5,mo=998244353;
int p[N],mu[N];
bool bz[N];
ll n,ans;
void prepare(int n) {
mu[1]=1;
fo(i,2,n) {
if (!bz[i]) p[++p[0]]=i,mu[i]=-1;
fo(j,1,p[0]) {
int k=i*p[j];if (k>n) break;
bz[k]=1;if (!(i%p[j])) break;
mu[k]=-mu[i];
}
}
}
int main() {
scanf("%lld",&n);
int m=sqrt(n);
prepare(m);
fo(i,1,m) {
if (!mu[i]) continue;
int sum=0;ll nn=n/i/i;
for(ll l=1,r;l<=nn;l=r+1) {
r=nn/(nn/l);
(sum+=(ll)(r-l+1)*(nn/l)%mo)%=mo;
}
if (mu[i]==1) (ans+=sum)%=mo;
else (ans+=mo-sum)%=mo;
}
printf("%d\n",ans);
}