Min_25 筛板子70,最后3个点挂了。
#include<cstdio>
#include<cmath>
const long long mo=1e9+7;
long long n,w[200010],tot;
int qt,prime[100010],cnt,gp1[100010],gp2[100010],g1[200010],g2[200010],id1[100010],id2[100010];
bool v[100010];
inline int S(long long x,int y)
{
if (prime[y]>=x) return 0;
int p=x<=qt?id1[x]:id2[n/x];
int ans=((0ll+g2[p]-g1[p]-(gp2[y]-gp1[y]))%mo+mo)%mo;
for (int i=y+1;i<=cnt;i++)
{
if (1ll*prime[i]*prime[i]>x) break;
long long pe=prime[i];
for (int e=1;pe<=x;e++,pe*=prime[i])
{
int o=pe%mo;
ans=(ans+1ll*o*(o-1)%mo*(S(x/pe,i)+(e!=1)))%mo;
}
}
return ans;
}
int main()
{
scanf("%d",&n);
qt=sqrt(n);v[1]=true;
for (int i=2;i<=qt;i++)
{
if (!v[i]) prime[++cnt]=i;
for (int j=1;j<=cnt;j++)
{
if (i*prime[j]>qt) break;
v[i*prime[j]]=true;
if (i%prime[j]==0) break;
}
}
for (int i=1;i<=cnt;i++)
gp1[i]=(gp1[i-1]+prime[i])%mo,gp2[i]=(gp2[i-1]+1ll*prime[i]*prime[i])%mo;
for (long long l=1,r;l<=n;l=r+1)
{
r=n/(n/l);w[++tot]=n/r;
g1[tot]=w[tot]%mo;
g2[tot]=(1ll*g1[tot]*(g1[tot]+1)%mo*(g1[tot]*2+1)%mo*166666668%mo-1)%mo;
g1[tot]=(1ll*g1[tot]*(g1[tot]+1)%mo*500000004-1)%mo;
if(n/r<=qt) id1[n/r]=tot;else id2[r]=tot;
}
for (int i=1;i<=cnt;i++)
{
for (int j=1;j<=tot;j++)
{
if (1ll*prime[i]*prime[i]>w[j]) break;
long long p=w[j]/prime[i];
p=(p<=qt?id1[p]:id2[n/p]);
g1[j]=(g1[j]-1ll*prime[i]*(g1[p]-gp1[i-1]+mo)%mo+mo)%mo;
g2[j]=(g2[j]-1ll*prime[i]*prime[i]%mo*(g2[p]-gp2[i-1]+mo)%mo+mo)%mo;
}
}
printf("%d\n",(S(n,0)+1)%mo);
return 0;
}