本人在LOJ的第三题(前两题太水不好意思说了QwQ),欢迎大家踩std。
题目链接:LOJ
题目大意:定义函数 $f$:($minp$ 表示最小质因子)
$$f(x)=egin{cases}0&x=1\x-2&xin prime\minp(x)-1&otherwiseend{cases}$$
求 $f$ 前 $n$ 项的和对 $20190601$ 取模的值。
$1le nle 10^{11}$。
考虑 min_25 筛中的 $g_0(n,j)$($0$ 次方,即满足条件的数的个数)和 $g_0(n,j-1)$。
$g_0(n,j)=sumlimits^n_{i=1}[iin prime || minp(i)>p_j]$
$g_0(n,j-1)=sumlimits^n_{i=1}[iin prime || minp(i)ge p_j]$
特别地,有 $g_0(n,0)=n-1$。
所以 $g_0(n,j-1)-g_0(n,j)=sumlimits^n_{i=1}[i otin prime && minp(i)=p_j]$。
也就是最小质因子为 $p_j$ 的数的个数。(不包括 $p_j$)
那么答案为 $sumlimits^{|P|}_{j=1}p_j(g_0(n,j-1)-g_0(n,j)+1)-(n-1)-g_0(n,|P|)$。
……吗?
由于 min_25 筛只能处理到 $le sqrt{n}$ 的质数,所以 $>sqrt{n}$ 的质数不会被统计到。
所以分质数和合数两类讨论。合数部分上面讨论完了。质数部分是模板。
答案为 $sumlimits^{|P|}_{j=1}p_j(g_0(n,j-1)-g_0(n,j))+g_1(n,|P|)-(n-1)-g_0(n,|P|)$。
时间复杂度 $O(dfrac{n^{3/4}}{log n})$。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=700070,mod=20190601; #define FOR(i,a,b) for(int i=(a);i<=(b);i++) #define ROF(i,a,b) for(int i=(a);i>=(b);i--) #define MEM(x,v) memset(x,v,sizeof(x)) ll n,w[maxn]; int sq,tot,g1[maxn],g0[maxn],s1[maxn],pr[maxn],pl,id1[maxn],id2[maxn],g[maxn],ans,mn[maxn]; bool vis[maxn]; inline int add(int x,int y){return x+y<mod?x+y:x+y-mod;} inline int sub(int x,int y){return x<y?x-y+mod:x-y;} inline int id(ll x){return x<=sq?id1[x]:id2[n/x];} void init(){ sq=sqrt(n); FOR(i,2,sq){ if(!vis[i]) pr[++pl]=i,s1[pl]=(s1[pl-1]+i)%mod; FOR(j,1,pl){ if(i*pr[j]>sq) break; vis[i*pr[j]]=true; mn[i*pr[j]]=pr[j]; if(i%pr[j]==0) break; } } for(ll l=1,r;l<=n;l=r+1){ r=n/(n/l); w[++tot]=n/l; if(n/l<=sq) id1[n/l]=tot; else id2[n/(n/l)]=tot; int t=w[tot]%mod; g0[tot]=sub(t,1); g1[tot]=(1ll*t*(t+1)/2-1)%mod; } } void calc_g(){ FOR(i,1,pl) FOR(j,1,tot){ if(1ll*pr[i]*pr[i]>w[j]) break; int pre=g0[j]; g0[j]=sub(g0[j],sub(g0[id(w[j]/pr[i])],i-1)); g1[j]=sub(g1[j],1ll*pr[i]*sub(g1[id(w[j]/pr[i])],s1[i-1])%mod); if(w[j]==n) g[i]=sub(pre,g0[j]); } } int main(){ scanf("%lld",&n); init(); calc_g(); FOR(i,1,pl) ans=add(ans,1ll*pr[i]*g[i]%mod); ans=add(ans,sub(g1[id(n)],g0[id(n)])); ans=sub(ans,(n-1)%mod); printf("%d ",ans); }