===s(n)∑i=1nf(n)∑i=1n(i2−3i+2)−∑i=1n∑d|i,d<if(d)n(n+1)(2n+1)6−3n(n+1)2+2n−∑i=2n∑d=1⌊ni⌋f(d)
杜教筛即可。预处理的时候做不到线性了,但是仍然可以 O(klogk) 做到。
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=800000,maxm=3000000,p=1000000007,mod=1000007,inv2=500000004,inv6=166666668;
int f[maxn+10],sum[maxn+10],fir[mod+10],ne[maxm],val[maxm],ans[maxm],tot;
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;
return x<0?x+p:x;
}
int get(int n)
{
return inc(dec((LL)n*(n+1)%p*(2*n+1)%p*inv6%p,3LL*n%p*(n+1)%p*inv2%p),2*n%p);
}
int find(int n)
{
for (int i=fir[n%mod];i;i=ne[i])
if (val[i]==n) return ans[i];
return -1;
}
void ins(int n,int x)
{
int y=n%mod;
tot++;
ne[tot]=fir[y];
fir[y]=tot;
val[tot]=n;
ans[tot]=x;
}
int calc(int n)
{
if (n<=maxn) return sum[n];
int ret=find(n);
if (ret>=0) return ret;
ret=get(n);
for (int i=2,j;i<=n;i=j+1)
{
j=n/(n/i);
ret=dec(ret,(LL)(j-i+1)*calc(n/i)%p);
}
ins(n,ret);
return ret;
}
int main()
{
for (int i=1;i<=maxn;i++)
{
f[i]=inc(f[i],inc(dec((LL)i*i%p,3*i%p),2));
sum[i]=inc(sum[i-1],f[i]);
for (int j=i+i;j<=maxn;j+=i)
f[j]=dec(f[j],f[i]);
}
int T,n;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
printf("%d\n",calc(n));
}
}