题目
分析
先把
max
{
i
,
j
}
\max\{i, j\}
max{i,j} 去掉:
原
式
=
2
∑
i
=
1
N
∑
j
=
1
i
i
σ
(
i
j
)
−
∑
i
=
1
N
i
σ
(
i
2
)
原式=2\sum_{i = 1}^{N}\sum_{j = 1}^i i\sigma(ij)-\sum_{i = 1}^N i\sigma(i^2)
原式=2i=1∑Nj=1∑iiσ(ij)−i=1∑Niσ(i2)
推式子前先介绍约数和函数有一个重要性质(和约数个数一样可以转化为 gcd \gcd gcd 问题): σ ( x y ) = ∑ i ∣ x ∑ j ∣ y i j [ gcd ( i , y j ) = 1 ] = ∑ i ∣ x ∑ j ∣ y i y j [ gcd ( i , j ) = 1 ] \begin{aligned}\sigma(xy)=&\sum_{i|x}\sum_{j|y}ij\left[\gcd\left(i, \frac{y}{j}\right)=1\right]\\=&\sum_{i| x}\sum_{j|y}i\frac{y}{j}[\gcd(i, j) = 1]\end{aligned} σ(xy)==i∣x∑j∣y∑ij[gcd(i,jy)=1]i∣x∑j∣y∑ijy[gcd(i,j)=1] 证明时考虑我们从 x x x 中枚举一个因数 i i i,从 y y y 中枚举一个因数 j j j,为了确保不算重,我们规定同一个质因子先从 y y y 中取到 j j j 里面,取完了再从 x x x 中取到 i i i 里面,这样的话所有 i j ij ij 都是 x y xy xy 的因数且不会算重。如何保证每个质因子都是先从 y y y 中取的呢?只需要看 y j \frac{y}{j} jy 中的某个质因数在不在 i i i 中,如果在,就意味着 y y y 中的这个质因数还没有取完,我们就从 x x x 中取了,这是不合法的,于是第一个等号得证,第二个等号就显然了。
先算第一个部分,代入上面的公式: ∑ i = 1 N ∑ j = 1 i i σ ( i j ) = ∑ i = 1 N ∑ j = 1 i i ∑ x ∣ i ∑ y ∣ j x j y [ gcd ( x , y ) = 1 ] \begin{aligned}&\sum_{i = 1}^{N}\sum_{j = 1}^i i\sigma(ij)\\=&\sum_{i = 1}^{N}\sum_{j = 1}^i i\sum_{x|i}\sum_{y|j}x\frac{j}{y}[\gcd(x, y) = 1]\end{aligned} =i=1∑Nj=1∑iiσ(ij)i=1∑Nj=1∑iix∣i∑y∣j∑xyj[gcd(x,y)=1] 反演一下上式变为 ∑ i = 1 N ∑ j = 1 i i ∑ x ∣ i ∑ y ∣ j x j y ∑ d ∣ gcd ( x , y ) μ ( d ) = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 i d i ∑ d ∣ d x ∣ d i ∑ d ∣ d y ∣ d j d x d j d y = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 i d i ∑ x ∣ i ∑ y ∣ j d x d j d y = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 i d i ∑ x ∣ i d x ∑ y ∣ j j y = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ d 2 i ∑ x ∣ i x ∑ j = 1 i ∑ y ∣ j y = ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) ∑ j = 1 i σ ( j ) \begin{aligned}&\sum_{i = 1}^{N}\sum_{j = 1}^i i\sum_{x|i}\sum_{y|j}x\frac{j}{y}\sum_{d|\gcd(x, y)} \mu(d)\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}\sum_{j = 1}^{i}di\sum_{d|dx|di}\sum_{d|dy|dj}dx\frac{dj}{dy}\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}\sum_{j = 1}^{i}di\sum_{x|i}\sum_{y|j}dx\frac{dj}{dy}\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}\sum_{j = 1}^{i}di\sum_{x|i}dx\sum_{y|j}\frac{j}{y}\\=&\sum_{d = 1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}d^2i\sum_{x|i}x\sum_{j = 1}^{i}\sum_{y|j}y\\=&\sum_{d = 1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)\sum_{j = 1}^{i}\sigma(j)\end{aligned} =====i=1∑Nj=1∑iix∣i∑y∣j∑xyjd∣gcd(x,y)∑μ(d)d=1∑Nμ(d)i=1∑⌊dN⌋j=1∑idid∣dx∣di∑d∣dy∣dj∑dxdydjd=1∑Nμ(d)i=1∑⌊dN⌋j=1∑idix∣i∑y∣j∑dxdydjd=1∑Nμ(d)i=1∑⌊dN⌋j=1∑idix∣i∑dxy∣j∑yjd=1∑Nμ(d)i=1∑⌊dN⌋d2ix∣i∑xj=1∑iy∣j∑yd=1∑Nμ(d)d2i=1∑⌊dN⌋iσ(i)j=1∑iσ(j) 令 S ( x ) = ∑ i = 1 x σ ( i ) S(x)=\sum\limits_{i = 1}^x \sigma(i) S(x)=i=1∑xσ(i),别忘了还要最后乘个 2 2 2: 2 ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) S ( i ) 2\sum_{d = 1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)S(i) 2d=1∑Nμ(d)d2i=1∑⌊dN⌋iσ(i)S(i) 再考虑第二部分,继续代入公式,差不多的方法: ∑ i = 1 N i σ ( i 2 ) = ∑ i = 1 N i ∑ x ∣ i ∑ y ∣ j x i y [ gcd ( x , y ) = 1 ] = ∑ d = 1 N μ ( d ) ∑ i = 1 ⌊ N d ⌋ d i ∑ x ∣ i d x ∑ y ∣ i i y = ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ 2 ( i ) \begin{aligned}&\sum_{i = 1}^N i\sigma(i^2)\\=&\sum_{i = 1}^Ni\sum_{x|i}\sum_{y|j}x\frac{i}{y}[\gcd(x,y)=1]\\=&\sum_{d=1}^N\mu(d)\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}di\sum_{x|i}dx\sum_{y|i}\frac{i}{y}\\=&\sum_{d=1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma^2(i)\end{aligned} ===i=1∑Niσ(i2)i=1∑Nix∣i∑y∣j∑xyi[gcd(x,y)=1]d=1∑Nμ(d)i=1∑⌊dN⌋dix∣i∑dxy∣i∑yid=1∑Nμ(d)d2i=1∑⌊dN⌋iσ2(i) 两部分合起来: 原 式 = 2 ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) S ( i ) − ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ 2 ( i ) = ∑ d = 1 N μ ( d ) d 2 ∑ i = 1 ⌊ N d ⌋ i σ ( i ) ( 2 S ( i ) − σ ( i ) ) \begin{aligned} 原式=&2\sum_{d = 1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)S(i)-\sum_{d=1}^N\mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma^2(i)\\=&\sum_{d=1}^N \mu(d)d^2\sum_{i = 1}^{\left\lfloor\frac{N}{d}\right\rfloor}i\sigma(i)(2S(i)-\sigma(i))\end{aligned} 原式==2d=1∑Nμ(d)d2i=1∑⌊dN⌋iσ(i)S(i)−d=1∑Nμ(d)d2i=1∑⌊dN⌋iσ2(i)d=1∑Nμ(d)d2i=1∑⌊dN⌋iσ(i)(2S(i)−σ(i)) 如果询问少的话可以 O ( N + T N ) O(N + T\sqrt N) O(N+TN) 做。
其实所有形如 A ( N ) = ∑ i = 1 N f ( i ) ∑ j = 1 ⌊ N i ⌋ g ( j ) = ∑ i = 1 N ∑ j = 1 ⌊ N i ⌋ f ( i ) g ( j ) A(N)=\sum\limits_{i=1}^{N}f(i)\sum\limits_{j=1}^{\left\lfloor\frac{N}{i}\right\rfloor}g(j)=\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{\left\lfloor\frac{N}{i}\right\rfloor}f(i)g(j) A(N)=i=1∑Nf(i)j=1∑⌊iN⌋g(j)=i=1∑Nj=1∑⌊iN⌋f(i)g(j) 的式子在已知 f , g f, g f,g 时都可以 O ( N ln N ) O(N\ln N) O(NlnN) 预处理所有的 A A A 值。因为它能递推: A ( N ) = A ( N − 1 ) + ( f ∗ g ) ( N ) A(N)=A(N - 1) + (f * g)(N) A(N)=A(N−1)+(f∗g)(N) 考虑 A ( N ) A(N) A(N) 比 A ( N − 1 ) A(N - 1) A(N−1) 多出来的东西,无非是当 i ∣ N i|N i∣N 时, ⌊ N i ⌋ \left\lfloor\frac{N}{i}\right\rfloor ⌊iN⌋ 多了一个 g ( N i ) g\left(\frac{N}{i}\right) g(iN),因此 A ( N ) = A ( N − 1 ) + ∑ i ∣ N f ( i ) g ( N i ) = A ( N − 1 ) + ( f ∗ g ) ( N ) A(N) = A(N - 1) + \sum_{i|N}f(i)g\left(\frac{N}{i}\right)=A(N - 1) + (f * g)(N) A(N)=A(N−1)+i∣N∑f(i)g(iN)=A(N−1)+(f∗g)(N) 然后我们用调和级数复杂度算出所有 f ∗ g f*g f∗g, A A A 就是他们的前缀和!
换到这道题上, f ( x ) = μ ( x ) x 2 , g ( x ) = x σ ( x ) ( 2 S ( x ) − σ ( x ) ) f(x)=\mu(x)x^2, g(x)=x\sigma(x)(2S(x)-\sigma(x)) f(x)=μ(x)x2,g(x)=xσ(x)(2S(x)−σ(x)),先线筛 μ \mu μ 和 σ \sigma σ,然后预处理即可。
代码
#include <bits/stdc++.h>
int Read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = x * 10 + (c ^ 48), c = getchar();
return x;
}
typedef long long LL;
const int MAXN = 1000000;
const int MOD = 1000000007;
inline int Add(int x, const int &y) {
return ((x += y) >= MOD) ? (x - MOD) : x;
}
inline int Mul(const int &x, const int &y) {
return (LL)x * y % MOD;
}
inline int Sub(int x, const int &y) {
return ((x -= y) < 0) ? (x + MOD) : x;
}
int Mu[MAXN + 5];
LL Sig[MAXN + 5], Low[MAXN + 5];
bool Vis[MAXN + 5];
std::vector<int> Pri;
int Ans[MAXN + 5], S[MAXN + 5];
void Init(int n) {
Mu[1] = Sig[1] = Low[1] = S[1] = 1;
for (int i = 2; i <= n; i++) {
if (!Vis[i])
Mu[i] = MOD - 1, Sig[i] = Low[i] = 1 + i, Pri.push_back(i);
for (int j = 0, k; j < (int)Pri.size() && i * Pri[j] <= n; j++) {
Vis[k = i * Pri[j]] = true;
if (i % Pri[j] == 0) {
Mu[k] = 0;
Low[k] = 1 + Low[i] * Pri[j];
Sig[k] = Sig[i] / Low[i] * Low[k];
break;
}
Mu[k] = MOD - Mu[i];
Low[k] = 1 + Pri[j];
Sig[k] = Sig[i] * Low[k];
}
S[i] = Add(S[i - 1], Sig[i] % MOD);
}
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j += i)
Ans[j] = Add(Ans[j], Mul(Mu[i], Mul(i, Mul(i, Mul(j / i, Mul(Sig[j / i], Sub(Mul(2, S[j / i]), Sig[j / i])))))));
for (int i = 1; i <= n; i++)
Ans[i] = Add(Ans[i], Ans[i - 1]);
}
int main() {
Init(MAXN);
int T = Read(), Cas = 0;
while (T--)
printf("Case #%d: %d\n", ++Cas, Ans[Read()]);
return 0;
}