Loj 6053 简单的函数 Posted on 2019-05-28 | Views: min_25 筛 . 除了 $2$ 之外的质数 $p$ 都是奇数, $f(p)=p-1$ ,而 $f(2)=3$ . 把 $f(p)$ 都当成 $f(p)=p-1$ ,用 min_25 筛法来做.有 $2$ 就特判一下, $+2$ 就好了. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103#include<bits/stdc++.h>using namespace std;typedef long long ll;inline ll read(){ ll out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=2e5+10;const int P=1e9+7;const int inv2=(P+1)>>1;inline int add(ll a,ll b){ a%=P; b%=P; return (a + b) % P;}inline int mul(ll a,ll b){ a%=P; b%=P; return 1LL * a * b % P;}ll n,sqr,w[MAXN];int cnt=0,ism[MAXN],sump[MAXN],m;ll prime[MAXN];ll id1[MAXN],id2[MAXN];void init(int N){ ism[1]=1; for(int i=2;i<=N;++i) { if(!ism[i]) { prime[++cnt]=i; sump[cnt]=add(sump[cnt-1],i); } for(int j=1;j<=cnt && prime[j]*i<=N;++j) { ism[prime[j]*i]=1; if(i%prime[j]==0) break; } }}int h[MAXN],g[MAXN],ans;int S(ll x,int y){ if(x<=1 || prime[y]>x) return 0; int k=(x<=sqr)?id1[x]:id2[n/x]; int res=add(g[k]-sump[y-1],y-h[k]-1); if(y==1) res+=2; for(int i=y;i<=cnt && 1LL*prime[i]*prime[i]<=x;++i) { ll pow1=prime[i],pow2=1LL*prime[i]*prime[i]; for(int e=1;pow2<=x;++e,pow1=pow2,pow2*=prime[i]) { int tmp=mul(S(x/pow1,i+1),prime[i]^e); tmp=add(tmp,prime[i]^(e+1)); res=add(res,tmp); } } return res;}int main(){ n=read(); sqr=sqrt(n); init(sqr); for(ll l=1,r;l<=n;l=r+1) { ll &i=l,&j=r; r=n/(n/l); w[++m]=n/l; h[m]=add(w[m]%P,-1); g[m]=mul(w[m],w[m]+1); g[m]=mul(g[m],inv2); g[m]=add(g[m],-1); if(w[m]<=sqr) id1[n/l]=m; else id2[r]=m; } for(int j=1;j<=cnt;++j) for(int i=1;i<=m && prime[j]*prime[j]<=w[i];++i) { int k=(w[i]/prime[j]<=sqr)?id1[w[i]/prime[j]]:id2[n/(w[i]/prime[j])]; g[i]=add(g[i],-mul(prime[j],add(g[k],-sump[j-1]))); h[i]=add(h[i],j-h[k]-1); } ans=add(S(n,1),1); cout<<(ans+P)%P<<endl; return 0;}