I copied the template solution with understanding to deepen my impression
Du Jiao sieve can be used to solve the prefix and of integral function. However, when this kind of integral function is not common and it is not difficult to roll out the functions that have been used to calculate the prefix sum, Du Jiao sieve is weak. At this time, Min-25 screen can be considered.
The following contents agree that \ (p\in\mathbb{P} \), \ (p_i \) is the prime number with the largest \ (I \).
Use Min_25 sieve conditions: the function (let it be \ (F \)) is an integral function, and \ (F(p^k) \) is a lower order polynomial about \ (p \).
The limitation of lower order polynomials is because Min_25 sieve is mainly used to find the prefix sum of \ (f(p)=p^k \), divide the polynomial into several monomials, find the prefix and sum respectively, and then add them to get the answer.
Min_ The solution of 25 sieve is mainly divided into two steps.
Step1 classification
We classify \ (\ sum {I = 1} ^ NF (I) \) by prime and composite numbers.
Enumerate the minimum prime factor for the latter part to meet the limit. Let \ (lpf_i \) be the minimum prime factor of \ (I \),
So the two parts are solved separately.
Step 2 solve
Part I
It is certainly unrealistic to screen out all \ (f(p) \) linearly. We define \ (g {n, I} \) as the sum of all prime numbers within \ (n \) and the \ (k \) power of the number whose minimum prime factor is greater than \ (P _, I \). What we require is \ (g(x,\sqrt x) \), and consider DP to find this thing.
\(g(n,0) \) can be calculated by \ (O(1) \), and consider how to transfer from \ (g(n,j-1) \) to \ (g(n,j) \). The part removed in this step is the composite \ (k \) power value with the minimum prime factor of \ (p_j \) and not greater than \ (n \).
The latter \ (g \) removes all prime numbers less than \ (p_j \).
In fact, all we need is \ (g(x,p_y) \), where \ (p_y \) is the last prime number less than \ (x \). Call it \ (pw_x \).
Solve the answer
Continue to set \ (s {n, X} \) as the sum of the number function values in \ ([1,n] \) whose minimum prime factor is greater than \ (P _x \). Continue to consider the transfer of classification. The first part is a prime number greater than \ (p_x \), which can be written as \ (pw_n-pw_x \). The other part is the residual composite number, which can be solved recursively.
Then it is found that we only need the value of \ (PW \) at \ (\ frac{n}{x} \), because the minimum prime factor of the composite number does not exceed the root sign, so \ (pw_x \) can be preprocessed directly. Therefore, when solving \ (g \), only \ (O(\sqrt n) \) values are required.
details
During discretization, two arrays can be opened to record the discretized positions of \ (\ frac{n}{x} \) and \ (\ frac{n}{\frac{n}{x} \) respectively. When saving, which can be saved at which age, which can ensure that the size of the array is \ (O(\sqrt n) \).
The contribution of 1 is calculated separately, and one is added at the end.
\(code:\)
P5325 [template] Min_25 sieve#include<bits/stdc++.h> using namespace std; namespace IO{ #define int LL typedef long long LL; int read(){ int x=0,f=0; char ch=getchar(); while(ch<'0'||ch>'9'){ f|=ch=='-'; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return f?-x:x; } char outp[50]; void write(int x,char sp){ int len=0; if(x<0) x=-x, putchar('-'); do{ outp[len++]=x%10+'0'; x/=10; }while(x); for(int i=len-1;~i;i--) putchar(outp[i]); putchar(sp); } } using namespace IO; const int NN=300010,mod=1e9+7,inv3=333333336; int n,sqr; void pls(int& x,int y){ (x+=y)>=mod?(x-=mod):(x<0?(x+=mod):0); } namespace Min_25{ int cnt,pri[NN],p1[NN],p2[NN]; int tot,g1[NN],g2[NN],has[NN],pos1[NN],pos2[NN]; bool vis[NN]; void sieve(int n){ p1[1]=p2[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]){ pri[++cnt]=i; pls(p1[cnt]=p1[cnt-1],i); pls(p2[cnt]=p2[cnt-1],i*i%mod); } for(int j=1;j<=cnt&&i*pri[j]<=n;j++){ vis[i*pri[j]]=1; if(i%pri[j]==0) break; } } } void divblock(){ for(int l=1,r;l<=n;l=r+1){ r=n/(n/l); has[++tot]=n/l; g1[tot]=has[tot]%mod; pls(g2[tot]=g1[tot]*(g1[tot]+1)/2%mod*(g1[tot]*2+1)%mod*inv3%mod,-1); pls(g1[tot]=g1[tot]*(g1[tot]+1)/2%mod,-1); n/l<=sqr?pos1[n/l]=tot:pos2[r]=tot; } } void getg(){ for(int i=1;i<=cnt;i++) for(int j=1;j<=tot&&pri[i]*pri[i]<=has[j];j++){ int k=has[j]/pri[i]<=sqr?pos1[has[j]/pri[i]]:pos2[n/(has[j]/pri[i])]; pls(g1[j],-pri[i]*(g1[k]-p1[i-1])%mod); pls(g2[j],-pri[i]*pri[i]%mod*(g2[k]-p2[i-1])%mod); } } int calc(int x,int y,int res=0){ if(pri[y]>=x) return 0; int k=x<=sqr?pos1[x]:pos2[n/x]; pls(res,(g2[k]-g1[k]+p1[y]-p2[y])%mod); for(int i=y+1;i<=cnt&&pri[i]*pri[i]<=x;i++) for(int j=1,p=pri[i];p<=x;j++,p=p*pri[i]){ int pp=p%mod; pls(res,pp*(pp-1)%mod*(calc(x/p,i)+(j!=1))%mod); } return res; } } using namespace Min_25; signed main(){ n=read(); sqr=sqrt(n); sieve(sqr); divblock(); getg(); write((calc(n,0)+1)%mod,'\n'); return 0; }