2020 Wannafly Day3 D.求和(反演,杜教筛)

求和

https://ac.nowcoder.com/acm/contest/4114/D


求和



图片说明



图片说明


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod;
const int N=1e6+6;
bool vis[N];
ll prime[N],phi[N],tot;
ll cal_2(__int128 n){
    __int128 x=n*(n+1)*(n*2+1)/6;
    return x%mod;
}
ll cal_1(__int128 n){
    __int128 x=n*(n+1)/2;
    return x%mod;
}
void pre(){
    phi[1]=1;
    for(int i=2;i<N;i++){
        if(!vis[i])prime[++tot]=i,phi[i]=i-1;
        for(int j=1;j<=tot&&i*prime[j]<N;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=1;i<N;i++)phi[i]=(phi[i]+phi[i-1])%mod;
}
map<int,ll>p;
ll s(ll n){
    if(n<N)return phi[n];
    if(p[n])return p[n];
    ll ans=cal_1(n);
    for(ll i=2,last;i<=n;i=last+1){
        last=n/(n/i);
        ll x=(last-i+1)%mod;
        ans-=s(n/i)*x%mod;
        ans=(ans%mod+mod)%mod;
    }
    return p[n]=ans;
}
int main(){
    ll n;
    scanf("%lld%lld",&n,&mod);
    pre();
    ll ans=0;
    for(ll i=1,last;i<=n;i=last+1){
        last=n/(n/i);
        ll x=(cal_2(last)-cal_2(i-1)+mod)%mod;
        ans+=s(n/i)*x%mod;
        if(ans>=mod)ans%=mod;
        if(ans<0)ans+=mod;
    }
    printf("%lld\n",ans);
}

全部评论
请问s(n)的推导是怎么看d?
点赞 回复 分享
发布于 2020-03-05 13:47

相关推荐

头顶尖尖的程序员:我也是面了三四次才放平心态的。准备好自我介绍,不一定要背熟,可以记事本写下来读。全程控制语速,所有问题都先思考几秒,不要急着答,不要打断面试官说话。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务