[luoguP3768]简单的数学题
题目
题解
反演经典题型,考虑将 \(\gcd\) 拿出来枚举,然后将柿子往下推
先定义 \(S(n)=1+2+3...+n=\frac{n(n+1)}{2}\).
当然在这一步你可以定义一个新函数,定义
然后原式就是
但是这样做会超时,时间复杂度大概是线性左右......
我们考虑将柿子硬推下去,令 \(T=dx,d={T\over x}\),同时我们有 \(\left\lfloor{\left\lfloor{n\over d}\right\rfloor\over x}\right\rfloor=\left\lfloor{n\over dx}\right\rfloor=\left\lfloor{n\over T}\right\rfloor\),考虑把柿子中的 \(d\) 都换成 \(T\),有
考虑将 \(\left({T\over x}\right)^3\) 中的 \(\left({1\over x}\right)^3\) 全部拿出来,就有
同时我们又有 \(\sum_{x|T}{\mu(x)\over x}={\varphi(T)\over T}\)(这一步可以去查莫比乌斯反演相关资料),那么就有
现在考虑怎么使用杜教筛解决 \(\sum T^2\varphi(T)\).
令 \(f(x)=x^2\varphi(x)\),同时令 \(h(x)=x^3,g(x)=x^2\),那么
即可以满足 \(h=f*g\),令 \(F(n)=\sum_{i=1}^nf(i)\),那么有
就可以进行杜教筛了.
求 \(Ans\) 时分块,但是分块需要求到 \(\sum T^2\varphi(T)\),就用上面的杜教筛处理前缀和作差可以求得这个东西.
代码
const int maxn=4e6;
ll n,mod,inv4,inv6;
ll S[maxn+5];
map<ll,ll>mS;
int prime[maxn>>2],pcnt;
inline void sieve(){
S[1]=1;
rep(i,2,maxn){
if(!S[i])prime[++pcnt]=i,S[i]=i-1;
for(int j=1;j<=pcnt && i*prime[j]<=maxn;++j){
if(i%prime[j]==0){
S[i*prime[j]]=S[i]*prime[j]%mod;
break;
}
S[i*prime[j]]=S[i]*S[prime[j]]%mod;
}
}
rep(i,1,maxn)S[i]=(1ll*i*i%mod*S[i]%mod+S[i-1])%mod;
}
inline ll qkpow(ll a,ll n){
ll ret=1;a%=mod;
for(;n>0;n>>=1,a=1ll*a*a%mod)
if(n&1)ret=1ll*ret*a%mod;
return ret;
}
inline ll cube(ll x){x%=mod;
return 1ll*x*x%mod*(x+1)%mod*(x+1)%mod*inv4%mod;
}
inline ll cube(const ll l,const ll r){
return (cube(r)-cube(l-1)+mod)%mod;
}
inline ll square(ll x){x%=mod;
return 1ll*x*(x+1)%mod*(2*x+1)%mod*inv6%mod;
}
inline ll square(const ll l,const ll r){
return (square(r)+mod-square(l-1))%mod;
}
inline ll sum(ll x){x%=mod;
return (1ll*x*(x+1)/2)%mod;
}
ll getS(const ll n){
if(n<=maxn)return S[n];
if(mS[n])return mS[n];
ll ret=cube(n);
for(ll l=2,r;l<=n;l=r+1){
r=n/(n/l);
ll tmp1=square(l,r);
ret=(ret+mod-tmp1*getS(n/l)%mod)%mod;
}
return mS[n]=ret;
}
inline ll getS(const ll l,const ll r){
return (getS(r)+mod-getS(l-1))%mod;
}
inline void init(){
mod=readin(1ll),n=readin(1ll);
inv4=qkpow(4,mod-2),inv6=qkpow(6,mod-2);
sieve();
}
signed main(){
init();
ll ans=0;
for(ll l=1,r;l<=n;l=r+1){
r=n/(n/l);
ll tmp1=sum(n/l);tmp1=1ll*tmp1*tmp1%mod;
// ll tmp1=cube(n/l);
ll tmp2=getS(l,r);
ans=(ans+1ll*tmp1*tmp2%mod)%mod;
}
writc(ans,'\n');
return 0;
}
用到の一些 \(\tt trick\)
首先需要熟悉这个等式
其次,在进行杜教筛推导的时候,用到
然后就是进行莫反的时候,用得比较经典的枚举公因数,内部出现需保证 \((i,j)=1\) 的布尔式,之后用
进行替换.
以及后面出现乘积 \(dx\) 时,考虑用 \(T\) 对 \(dx\) 进行替换,然后内外层循环反复外提化简.