「算法笔记」Min_25 筛

这里(加了密码)。虽然写的可能还算清楚,但还是不公开了吧 QwQ。

真的想看的 私信可能会考虑给密码 qwq。就放个板子:

//LOJ 6053 简单的函数 f(p^c)=p xor c 
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5,mod=1e9+7;
int n,s,tot,val[N],id1[N],id2[N],x,cnt,p[N],sum[N],g[N],h[N],inv2=500000004;
bool vis[N];
int id(int x){
    return x<=s?id1[x]:id2[n/x];
}
int S(int x,int y){
    if(x<=1||p[y]>x) return 0;
    int ans=((g[id(x)]-h[id(x)]-(sum[y-1]-(y-1)))%mod+mod)%mod;
    if(y==1) ans+=2;
    for(int i=y;i<=cnt&&p[i]*p[i]<=x;i++){ 
        int p1=p[i],p2=p[i]*p[i];
        for(int e=1;p2<=x;e++,p1=p2,p2*=p[i])
            ans=(ans+((p[i]^e)*S(x/p1,i+1)%mod+(p[i]^(e+1))%mod)%mod)%mod; 
    }
    return ans;
} 
signed main(){
    scanf("%lld",&n),s=sqrt(n); 
    vis[0]=vis[1]=1;
    for(int i=2;i<=s;i++){
        if(!vis[i]) p[++cnt]=i,sum[cnt]=(sum[cnt-1]+i)%mod;
        for(int j=1;j<=cnt&&i*p[j]<=s;j++){
            vis[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }
    for(int l=1,r=0;l<=n;l=r+1){ 
        r=n/(n/l),x=n/l,val[++tot]=x;
        if(x<=s) id1[x]=tot;
        else id2[n/x]=tot;
        x%=mod,g[tot]=(2+x)*(x-1)%mod*inv2%mod,h[tot]=(x-1)%mod; 
    }
    for(int j=1;j<=cnt;j++)
        for(int i=1;i<=tot&&p[j]*p[j]<=val[i];i++){ 
            g[i]=(g[i]-p[j]*(g[id(val[i]/p[j])]-sum[j-1])%mod+mod)%mod; 
            h[i]=(h[i]-(h[id(val[i]/p[j])]-(j-1))%mod+mod)%mod;
        } 
    printf("%lld\n",S(n,1)+1);
    return 0;
}
posted @ 2021-03-01 17:11  maoyiting  阅读(160)  评论(0编辑  收藏  举报