f(p^c)=p异或c
当p!=2时,f(p)=p-1
满足f在质数处是关于p的多项式,在质数的幂处可以快速求
所以可以用min_25筛
要预处理的是质数前缀和 以及 质数前缀个数和
这个数据范围一不小心就爆long long了。。。
#include<cmath> #include<cstdio> using namespace std; const int mod=1e9+7; typedef long long LL; #define N 200001 LL n; int sq; int pr[N],tot; bool vis[N]; LL w[N]; int m,id1[N],id2[N]; LL sump[N],g[N],h[N]; int MOD(LL x) { return x%mod; } void pre() { sq=sqrt(n); for(int i=2;i<=sq;++i) { if(!vis[i]) { pr[++tot]=i; sump[tot]=(sump[tot-1]+i)%mod; } for(int j=1;j<=tot && 1ll*pr[j]*i<=sq;++j) { vis[pr[j]*i]=true; if(!(i%pr[j])) break; } } LL j,x; for(LL i=1;i<=n;i=j+1) { j=n/(n/i); x=n/i; w[++m]=x; if(x<=sq) id1[x]=m; else id2[n/x]=m; g[m]=(1ll*MOD(x)*MOD(x+1)/2%mod-1+mod)%mod; h[m]=(x-1)%mod; } } void solve1() { int k; for(int j=1;j<=tot;++j) for(int i=1;i<=m && 1ll*pr[j]*pr[j]<=w[i];++i) { k=w[i]/pr[j]<=sq ? id1[w[i]/pr[j]] : id2[n/(w[i]/pr[j])]; g[i]=(g[i]-1ll*pr[j]*(g[k]-sump[j-1])%mod+mod)%mod; h[i]=(h[i]-(h[k]-(j-1))+mod)%mod; } } LL solve2(LL x,int j) { if(x<=pr[j]) return 0; int kk= x<=sq ? id1[x]: id2[n/x]; LL gg=(g[kk]-sump[j]-(h[kk]-j)+mod)%mod; if(!j) gg+=2; LL now,sum=0; for(int k=j+1;k<=tot && 1ll*pr[k]*pr[k]<=x;++k) { now=pr[k]; for(int e=1;now*pr[k]<=x;now*=pr[k],++e) { sum+=(pr[k]^e)%mod*solve2(x/now,k)%mod; sum+=(pr[k]^(e+1))%mod; sum%=mod; } } return (gg+sum)%mod; } int main() { scanf("%lld",&n); if(n==1) { printf("1"); return 0; } pre(); solve1(); printf("%lld",(solve2(n,0)+1)%mod); }