Solution
求
∑i=1n∑j=1nmax(i,j)⋅σ(i⋅j)
∑
i
=
1
n
∑
j
=
1
n
max
(
i
,
j
)
⋅
σ
(
i
⋅
j
)
Solution
写完了回头看发现还是比较套路的,第一次写八级题肥肠激动
首先考虑去掉max
ans=2∑i=1n∑j=1ii⋅σ(i⋅j)−∑i=1ni⋅σ(i2)
a
n
s
=
2
∑
i
=
1
n
∑
j
=
1
i
i
⋅
σ
(
i
⋅
j
)
−
∑
i
=
1
n
i
⋅
σ
(
i
2
)
我们知道 σ(n⋅m)=∑i|n∑j|m[gcd(i,j)=1]n⋅jm σ ( n ⋅ m ) = ∑ i | n ∑ j | m [ g c d ( i , j ) = 1 ] n ⋅ j m
然后此处略去一波套路得到
=∑d=1nμ(d)⋅d2∑i=1⌊nd⌋σ(i)⋅i∑j=1iσ(j)
=
∑
d
=
1
n
μ
(
d
)
⋅
d
2
∑
i
=
1
⌊
n
d
⌋
σ
(
i
)
⋅
i
∑
j
=
1
i
σ
(
j
)
这里就能用分块做了,然鹅根号的复杂度不足以跑过这题,考虑接着推
令 T=id T = i d ,可以得到
=∑T=1n∑d|Tμ(d)⋅t⋅T⋅σ(Td)∑i=1Tdσ(i)
=
∑
T
=
1
n
∑
d
|
T
μ
(
d
)
⋅
t
⋅
T
⋅
σ
(
T
d
)
∑
i
=
1
T
d
σ
(
i
)
大概就是介样,然后就可以枚举d然后nln预处理O(1)出解。注意不要忘了减去的那一部分
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (register LL i=st;i<=ed;++i)
typedef long long LL;
const int MOD=1000000007;
const int N=1000005;
LL low[N+5],d[N+5],dd[N+5],mu[N+5];
LL ans[N+5],s[N+5],tmp[N+5];
LL prime[N/5];
bool not_prime[N+5];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add(LL &x,LL v) {
x+=v; x-=(x>=MOD)?(MOD):(0);
}
void pre_work(int n) {
dd[1]=d[1]=mu[1]=1;
rep(i,2,n) {
if (!not_prime[i]) {
prime[++prime[0]]=i;
mu[i]=-1; d[i]=i+1;
low[i]=i; dd[i]=(i*i%MOD+i+1)%MOD;
}
for (int j=1;i*prime[j]<=n&&j<=prime[0];++j) {
int x=i*prime[j];
not_prime[x]=1;
if (i%prime[j]==0) {
mu[x]=0;
low[x]=low[i]*prime[j];
d[x]=(d[i]*prime[j]%MOD+d[i/low[i]])%MOD;
dd[x]=(dd[i]*prime[j]%MOD*prime[j]%MOD+dd[i/low[i]]*prime[j]%MOD+dd[i/low[i]])%MOD;
break;
}
low[x]=prime[j];
d[x]=d[i]*d[prime[j]]%MOD;
dd[x]=dd[i]*dd[prime[j]]%MOD;
mu[x]=-mu[i];
}
}
rep(i,1,n) s[i]=(s[i-1]+d[i])%MOD;
for (LL i=1;i<=n;i++) {
for (LL j=i;j<=n;j+=i) {
LL tmp=mu[i]*i%MOD*j%MOD*d[j/i]%MOD*s[j/i]%MOD;
add(ans[j],tmp);
}
}
rep(i,1,n) add(ans[i],ans[i-1]);
rep(i,1,n) add(tmp[i],(tmp[i-1]+i*dd[i]%MOD)%MOD);
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
pre_work(1000000);
for (int T=read(),n,cnt=0;T--;) {
n=read();
LL prt=(ans[n]*2%MOD-tmp[n]+MOD)%MOD;
prt=(prt+MOD)%MOD;
printf("Case #%d: %lld\n", ++cnt, prt);
}
return 0;
}