BSOJ5655【BZOJ4916】神犇和蒟蒻

题目

求:

\[\large A=\sum_{i=1}^n\mu(i^2),B=\sum_{i=1}^n\varphi(i^2) \]

BSOJ5655【BZOJ4916】神犇和蒟蒻

分析

首先第一问显然是 \(1\)

第二问很容易由结论转化:

\[\large \varphi(nm)=\varphi(n)\varphi(m)\frac{\gcd(n,m)}{\varphi(\gcd(n,m))} \]

那么就变成了:

\[\large \sum_{i=1}^n\varphi(i^2)=\sum_{i=1}^n\varphi(i)^2\frac i{\varphi(i)}=\sum_{i=1}^ni\cdot \varphi(i) \]

接下来的任务是求 \(f(x)=id(x)\cdot \varphi(x)\) 的前缀和。

考虑杜教筛,然后根据常见套路,可以卷上 \(id\)

\[\large (f*id)(n)=\sum_{d\vert n}d\cdot \varphi(d)\cdot\frac nd=n\sum_{d\vert n}\varphi(d)=n^2 \]

考虑这个 \(f\) 的前缀和:\(\large \sum\limits_{i=1}^ni^2=\frac{n(n+1)(2n+1)}{6}\) ,很好求。

再考虑 \(id\) 的前缀和,就是等差数列,也很好求。

那么就可以杜教筛了,这道题结束。

代码

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;bool f=false;char ch=getchar();
	while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
	while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
#define ll long long
#define ull unsigned long long
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define dep(i,y,x) for(int i=(y);i>=(x);i--)
const int N=1e7+5,M=2e5+5;
const ll V=1e9,t=1e7,MOD=1e9+7;
int prime[N],cnt,phi[N];
ll n,prep[N],Ans,Rev6,Rev2;
bool isprime[N];
inline ll inc(ll x,ll y){x+=y;return x>=MOD?x-MOD:x;}
inline void incc(ll &x,ll y){x+=y;if(x>=MOD) x-=MOD;}
inline void decc(ll &x,ll y){x-=y;if(x<0) x+=MOD;}
inline ll dec(ll x,ll y){x-=y;return x<0?x+MOD:x;}
bool vis[N];
inline void GetPrimes(ll d){
	phi[1]=prep[1]=1;
	for(ll i=2;i<=d;i++){
		if(!isprime[i]) prime[++cnt]=i,phi[i]=i-1;
		prep[i]=inc(prep[i-1],1ll*phi[i]*i%MOD);
		for(ll j=1;j<=cnt&&i*prime[j]<=d;j++){
			isprime[i*prime[j]]=true;
			if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j]%MOD;break;}
			phi[i*prime[j]]=phi[i]*(prime[j]-1)%MOD;
		}
	}
	return ;
}
unordered_map<ll,ll>prepp;
inline ll QuickPow(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1) res=res*x%MOD;
		x=x*x%MOD;
		y>>=1;
	}
	return res;
}
inline ll Getprephi(ll x){
	if(x<=t) return prep[x];//线性筛预处理 
	if(prepp[x]) return prepp[x]; 
	ll res=1ll*x*(x+1)%MOD*(2*x+1)%MOD*Rev6%MOD;
	for(ll l=2,r;l<=x;l=r+1){ 
		r=x/(x/l);
		decc(res,1ll*dec(r*(r+1)%MOD*Rev2%MOD,l*(l-1)%MOD*Rev2%MOD)*Getprephi(x/l)%MOD); 
	}
	return prepp[x]=(res+MOD)%MOD;
}
signed main(){
	read(n);
	GetPrimes(t);
	Rev6=QuickPow(6,MOD-2);
	Rev2=QuickPow(2,MOD-2);
	write(1),putchar('\n');
	write(Getprephi(n));
	return 0;
}
posted @ 2021-09-05 11:37  __Anchor  阅读(52)  评论(0)    收藏  举报