杜教筛提高

神犇和蒟蒻
根据 μ ( n ) \mu(n) μ(n) 的定义,当 n n n 为大于 1 1 1的完全平方数时 μ ( n ) = 0 \mu(n)=0 μ(n)=0,当 n = 1 n=1 n=1 μ ( n ) = 1 \mu(n)=1 μ(n)=1。因此 ∑ i = 1 n μ ( i 2 ) = 1 \sum_{i=1}^n \mu(i^2)=1 i=1nμ(i2)=1
对于 φ ( n 2 ) \varphi(n^2) φ(n2),先转化为 n φ ( n ) n \varphi(n) nφ(n),根据经验,将 φ \varphi φ 转化为约数的 φ \varphi φ 之和。即:
n = ∑ i ∣ n φ ( i ) n=\sum_{i|n}\varphi(i) n=inφ(i)
因此有:
∑ i = 1 n ∑ j ∣ i φ ( j ) i = ∑ i = 1 n i 2 = 1 6 n ( n + 1 ) ( 2 n + 1 ) \sum_{i=1}^n \sum_{j|i}\varphi(j)i=\sum_{i=1}^n i^2=\frac{1}{6}n(n+1)(2n+1) i=1njiφ(j)i=i=1ni2=61n(n+1)(2n+1)
换一种表达方法,先枚举约数,再枚举倍数:
∑ i = 1 n ∑ i ∣ j φ ( i ) j = ∑ i = 1 n φ ( i ) i ∑ j = 1 [ n i ] j = 1 6 n ( n + 1 ) ( 2 n + 1 ) \sum_{i=1}^n \sum_{i|j}\varphi(i)j=\sum_{i=1}^n \varphi(i)i \sum_{j=1}^{[\frac{n}{i}]}j=\frac{1}{6}n(n+1)(2n+1) i=1nijφ(i)j=i=1nφ(i)ij=1[in]j=61n(n+1)(2n+1)
不要忘了求解的目标:
∑ i = 1 n φ ( i ) i \sum_{i=1}^n \varphi(i)i i=1nφ(i)i
将其从式子中提出来,移项:
∑ i = 1 n φ ( i ) i = 1 6 n ( n + 1 ) ( 2 n + 1 ) + ∑ i = 1 [ n 2 ] φ ( i ) i ( 1 − ∑ j = 1 [ n i ] j ) \sum_{i=1}^n \varphi(i)i=\frac{1}{6}n(n+1)(2n+1)+\sum_{i=1}^{[\frac{n}{2}]}\varphi(i)i(1-\sum_{j=1}^{[\frac{n}{i}]}j) i=1nφ(i)i=61n(n+1)(2n+1)+i=1[2n]φ(i)i(1j=1[in]j)
因此最终的答案为:
1 6 n ( n + 1 ) ( 2 n + 1 ) + ∑ i = 1 [ n 2 ] φ ( i ) i ( 1 − 1 2 [ n i ] ( [ n i ] + 1 ) \frac{1}{6}n(n+1)(2n+1)+\sum_{i=1}^{[\frac{n}{2}]}\varphi(i)i(1-\frac{1}{2}[\frac{n}{i}]([\frac{n}{i}]+1) 61n(n+1)(2n+1)+i=1[2n]φ(i)i(121[in]([in]+1)
根据式子跑杜教筛即可。
时空复杂度 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)

#include<iostream>
#include<map>
using namespace std;
#define R register int
#define L long long
#define N 10000001
#define P 1000000007
int prime[664579],pre[N];
map<int,int>Q;
inline int Solve(int n){
	if(n<N){
		return pre[n];
	}
	if(Q.count(n)!=0){
		return Q[n];
	}
	int res=(1ll+n)*n%P*(n<<1|1)%P*166666668%P,r,lt=0,cur;
	for(R i=1;i<=n>>1;i=r+1){
		int tem=n/i;
		r=n/tem;
		cur=Solve(r);
		res+=(1-((1ll+tem)*tem>>1)%P)*(cur-lt)%P;
		if(res<0){
			res+=P;
		}else if(res>=P){
			res-=P;
		}
		lt=cur;
	}
	Q[n]=res;
	return res;
}
int main(){
	pre[1]=1;
	int n,ct=0;
	for(R i=2;i!=N;i++){
		if(pre[i]==0){
			pre[i]=i-1;
			prime[ct]=i;
			ct++;
		}
		for(R j=0;j!=ct&&i*prime[j]<N;j++){
			if(i%prime[j]==0){
				pre[i*prime[j]]=pre[i]*prime[j];
				break;
			}
			pre[i*prime[j]]=pre[i]*(prime[j]-1);
		}
		pre[i]=((L)pre[i]*i+pre[i-1])%P;
	}
	cin>>n;
	cout<<1<<endl<<Solve(n);
	return 0;
}
∑ i = 1 n μ ( i ) i m \sum_{i=1}^n \mu(i)i^m i=1nμ(i)im

1 ⩽ n ⩽ 1 0 9 , 1 ⩽ m ⩽ 200000 1 \leqslant n \leqslant 10^9,1 \leqslant m \leqslant 200000 1n109,1m200000
时间限制3s,空间限制32MB

题解

根据 μ ( n ) \mu(n) μ(n) 的定义,有 ∑ i ∣ n μ ( i ) = [ n = 1 ] \sum_{i|n} \mu(i)=[n=1] inμ(i)=[n=1],因此:
∑ i = 1 n ∑ j ∣ i μ ( j ) i m = 1 \sum_{i=1}^n \sum_{j|i} \mu(j)i^m=1 i=1njiμ(j)im=1
同样,换式子的形式,先枚举约数,再枚举倍数:
∑ i = 1 n μ ( i ) ∑ j = 1 [ n i ] ( i j ) m = 1 \sum_{i=1}^n \mu(i) \sum_{j=1}^{[\frac{n}{i}]}(ij)^m=1 i=1nμ(i)j=1[in](ij)m=1
f ( n ) = ∑ i = 1 n i m f(n)=\sum_{i=1}^n i^m f(n)=i=1nim,得到:
∑ i = 1 n μ ( i ) i m + ∑ i = 1 n μ ( i ) i m ( f ( [ n i ] ) − 1 ) = 1 \sum_{i=1}^n \mu(i)i^m+\sum_{i=1}^n \mu(i)i^m (f([\frac{n}{i}])-1)=1 i=1nμ(i)im+i=1nμ(i)im(f([in])1)=1
g ( n ) = ∑ i = 1 n μ ( i ) i m g(n)=\sum_{i=1}^n \mu(i)i^m g(n)=i=1nμ(i)im,有:
g ( n ) = 1 + ∑ i = 1 n μ ( i ) i m ( 1 − f ( [ n i ] ) ) g(n)=1+\sum_{i=1}^n \mu(i)i^m (1-f([\frac{n}{i}])) g(n)=1+i=1nμ(i)im(1f([in]))
由于 f ( 1 ) = 1 f(1)=1 f(1)=1,当 2 i > n 2i>n 2i>n 1 − f ( [ n i ] ) = 0 1-f([\frac{n}{i}])=0 1f([in])=0,因此可以在原式上进行修改:
g ( n ) = 1 + ∑ i = 1 [ n 2 ] μ ( i ) i m ( 1 − f ( [ n i ] ) ) g(n)=1+\sum_{i=1}^{[\frac{n}{2}]} \mu(i)i^m (1-f([\frac{n}{i}])) g(n)=1+i=1[2n]μ(i)im(1f([in]))
对于 f ( n ) f(n) f(n),可以取 f ( 0 ) , f ( 1 ) , f ( 2 ) ⋯ f ( m + 1 ) f(0),f(1),f(2) \cdots f(m+1) f(0),f(1),f(2)f(m+1)拉格朗日插值求出来。
时间复杂度 O ( n 2 3 + n 1 3 m ) O(n^{\frac{2}{3}}+n^{\frac{1}{3}}m) O(n32+n31m),空间复杂度 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)

#include<iostream>
#include<unordered_map>
using namespace std;
#define R register int
#define L long long
#define I inline
#define N 200002
#define M 3450001
#define P 998244353
int B[M],fac[N],inv[N],fac2[N],pre[M],prime[283146],m;
I int Add(int x,int y){
	x+=y;
	return x>=P?x-P:x;
}
I int PowMod(int x,int y){
	int res=1;
	while(y!=0){
		if((y&1)==1){
			res=(L)res*x%P;
		}
		y>>=1;
		x=(L)x*x%P;
	}
	return res;
}
unordered_map<int,int>Q,Q2;
I int GetB(int n){
	if(n<M){
		return B[n];
	}
	if(Q2.count(n)!=0){
		return Q2[n];
	}
	fac[0]=n;
	fac2[m+1]=n-m-1;
	if(fac2[m+1]<0){
		fac2[m+1]+=P;
	}
	for(R i=m;i!=0;i--){
		fac2[i]=(L)fac2[i+1]*(n-i)%P;
	}
	for(R i=1;i!=m+2;i++){
		fac[i]=(L)fac[i-1]*(n-i)%P;
	}
	int res=0;
	for(R i=1;i!=m+2;i++){
		int t=(L)B[i]*fac[i-1]%P*inv[i]%P;
		if(i<=m){
			t=(L)t*fac2[i+1]%P*inv[m+1-i]%P;
			if((m-i&1)==0){
				t=P-t;
			}
		}
		res=Add(res,t);
	}
	Q2[n]=res;
	return res;
}
I int GetA(int n){
	if(n<M){
		return pre[n];
	}
	if(Q.count(n)==1){
		return Q[n];
	}
	int r,lt=1,res=0;
	for(R i=2;i<=n;i=r+1){
		int tem=n/i,cur;
		r=n/tem;
		cur=GetB(r);
		res=((L)GetA(tem)*(cur-lt+P)+res)%P;
		lt=cur;
	}
	res=Add(1,P-res);
	Q[n]=res;
	return res;
}
int main(){
	int n,ct=0,f=1;
	cin>>n>>m;
	for(R i=1;i!=M;i++){
		pre[i]=1;
	}
	B[1]=1;
	for(R i=2;i!=M;i++){
		if(B[i]==0){
			prime[ct]=i;
			ct++;
			pre[i]=-1;
		}
		for(R j=0;j!=ct&&i*prime[j]<M;j++){
			int t=i*prime[j];
			B[t]=prime[j];
			if(i%prime[j]==0){
				pre[t]=0;
				break;
			}
			pre[t]=-pre[i];
		}
	}
	for(R i=2;i!=M;i++){
		if(B[i]==0){
			B[i]=PowMod(i,m);
		}else{
			B[i]=(L)B[i/B[i]]*B[B[i]]%P;
		}
		pre[i]=(L)pre[i]*B[i]%P;
		if(pre[i]<0){
			pre[i]+=P;
		}
	}
	for(R i=2;i!=M;i++){
		B[i]=Add(B[i],B[i-1]);
		pre[i]=Add(pre[i],pre[i-1]);
	}
	for(R i=1;i!=m+2;i++){
		f=(L)f*i%P;
	}
	inv[m+1]=PowMod(f,P-2);
	for(R i=m+1;i!=0;i--){
		inv[i-1]=(L)inv[i]*i%P;
	}
	cout<<GetA(n);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值