计算sigma(a=1~n)sigma(b=1~n)lcm(a,b).
oimaster的好题。
考虑a与b枚举是同域的,对于一个a只需统计比他小的的b,然后乘2即可,
则构造函数f[a]=-a+2*lcm(a,b)【b=1~a】;
设gcd(a,b)=d
f[a]=-a+2a*sigma(d|a)sigma(b<=a and gcd(a,b)=d) b/d
令b/d=k,
f[a]=-a+2a*sigma(d|a)sigma(k<=a/d and gcd(a/d,k)=1) k
因为(a/d)|a
则f[a]=-a+2a*sigma(d|a)sigma(k<=d and gcd(d,k)=1) k
做了这么多,其实只是想用一个公式,当n>1,1~n中与n互质的数的和为:(n*phi(n))/2
简略证明:对于一个与n互质的数d,n-d与n也互质,所以我们两两相加,一共有phi(n)/2对,而每对的和为n,得证。
f[a]=-a+2a*((sigma(d|a and d>1) d*phi(d)/2 )+ 1)
因为phi(1)=1
化解为f[a]=a*sigma(d|a) d*phi(d);
n为积性,phi为积性,所以f[a]为积性,
f[p^k]=(p^(3k+1)+p^k)/(p+1) 这一步我推了两次,每次都推错,明明是体力活的说。
得出递推式f[p^k]=p^3*f[p^(k-1)]-p^k*(p-1)
剩下就是线性筛法的事,论文上没说,我自己推了一下,却做不到线性。
如果是质数,就直接算。
如果正好包含p^1,则乘以f[p]
如果包含p^k,则设A*p^k=n,
现在已知f[A*p^(k-1)],设A*p^(k-1)=i;
f[n]=f[A]*f[p^k]=f[A]*(p^3*f[p^(k-1)]-p^k*(p-1))
=p^3*f[A]*f[p^(k-1)]-f[A]*p^k*(p-1)
=p^3*f[i]-f[A]*p^k*(p-1)
推不下去了,所以log的分解算了。
#include
#include
#include
#include
const int maxn=1000000;
long long f[maxn+1],s[maxn+1],phi[maxn+1],prim[maxn+1],tot,check[maxn+1];
long long sqt(long long x) {return x*x*x;}
void make(long long x,long long k,long long &ai,long long &bi)
{
ai=bi=0;
for (;x%k==0;) {
if (!bi) bi=(k-1);else bi*=k;
x/=k;
}
ai=x;
}
void origin()
{
long long ne,i,ai,bi,j;
phi[1]=1,f[1]=1;
tot=0;
for (i=2;i<=maxn;i++) {
if (!check[i]) {
prim[++tot]=i;
phi[i]=i-1;
f[i]=sqt(i)*f[1]-i*phi[i];
}
for (j=1;j<=tot;j++) {
ne=i*prim[j];
if (ne>maxn) break;
check[ne]=1;
if (i%prim[j]==0) {
phi[ne]=phi[i]*prim[j];
make(ne,prim[j],ai,bi);
f[ne]=sqt(prim[j])*f[i]-prim[j]*f[ai]*bi;
// f[ne]=sqt(prim[j])*f[i]-(prim[j]-1)*ai*bi;
break;
}
else {
phi[i*prim[j]]=phi[i]*(prim[j]-1);
f[ne]=f[i]*f[prim[j]];
}
}
}
for (i=1;i<=maxn;i++) s[i]=s[i-1]+f[i];
}
int main()
{
freopen("Archer.in","r",stdin);
freopen("Archer.out","w",stdout);
long long t,i,x;
origin();
scanf("%I64d\n",&t);
for (i=1;i<=t;i++) {
scanf("%I64d\n",&x);
printf("%I64d\n",s[x]);
}
return 0;
}