【洛谷】简单的数学题-莫比乌斯反演&杜教筛

传送门:luoguP3768


题解

这个方法比较复杂但是很有技巧性。

这个方法比较直接简洁。

(懒


代码

#include<bits/stdc++.h>
using namespace std;
const int N=8e6;
typedef long long ll;

ll n;int mod,iv2,iv6;
int p[N],tot,phi[N],ans,lim;
bool pri[N];
map<ll,int>mp;

inline int fp(int x,int y)
{
    int re=1;
    for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) re=(ll)re*x%mod;
    return re;
}

inline int ad(int x,int y){return ((ll)x+y)%mod;}
inline int dc(int x,int y){return ((ll)x-y+mod)%mod;}

inline void pre()
{
    lim=(n<N)?(int)n:(N-1);int re,i,j;phi[1]=1;
    for(int i=2;i<=lim;++i){
        if(!pri[i]) p[++tot]=i,phi[i]=i-1;
        for(j=1;j<=tot && (re=i*p[j])<=lim;++j){
            pri[re]=true;
            if(i%p[j]==0) {phi[re]=(ll)phi[i]*p[j]%mod;break;}
            phi[re]=(ll)phi[i]*phi[p[j]]%mod;
        }
    }
    for(i=2;i<=lim;++i) phi[i]=ad(phi[i-1],(ll)i*i%mod*(ll)phi[i]%mod);
}

inline int S(int x){return (ll)x*(x+1)%mod*(ll)iv2%mod;}
inline int Sp(int x){return (ll)x*(x+1)%mod*(ll)(((ll)x+x+1)%mod)%mod*(ll)iv6%mod;}

int F(ll x)
{
    if(x<=lim) return phi[x];
    if(mp[x]) return mp[x];
    int re=S(x%mod);re=(ll)re*re%mod;
    for(ll j,i=2;i<=x;i=j+1){
        j=x/(x/i);
        re=dc(re,(ll)dc(Sp(j%mod),Sp((i-1)%mod))*F(x/i)%mod);
    }
    return (mp[x]=re);
}

int main(){
    ll i,j;int ss,vl,pr=0;
    scanf("%d%lld",&mod,&n);pre();
    iv2=fp(2,mod-2);iv6=fp(6,mod-2);
    for(i=1;i<=n;i=j+1,pr=vl){
        j=n/(n/i);ss=S((n/i)%mod);ss=(ll)ss*ss%mod;
        vl=F(j);ans=ad(ans,(ll)ss*dc(vl,pr)%mod);
    }
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值