又是一道非常神奇的数论题,学到了很多又花了一晚上QWQ
【题目地址】
题目大意
多组询问 T ≤ 50000 T\leq 50000 T≤50000,每次给定一个 n ≤ 1 0 6 n\leq 10^6 n≤106,询问下面式子在 m o d 1 0 9 + 7 {\rm mod}\ 10^9+7 mod 109+7意义下的值:
∑ i = 1 n ∑ j = 1 n max ( i , j ) × σ 1 ( i j ) \sum_{i=1}^n\sum_{j=1}^n\max(i,j)\times \sigma_1(ij) i=1∑nj=1∑nmax(i,j)×σ1(ij)
其中 σ 1 ( i ) \sigma_1(i) σ1(i)表示 i i i的约数之和。
这次居然连 max \max max都跑进去了,emmmm…
我们还是先把不好看的 max \max max消除掉,所以对于每个 i i i,我们枚举比它小的 j j j,那么 max ( i , j ) = i \max(i,j)=i max(i,j)=i,由于 ( i , j ) , ( j , i ) (i,j),(j,i) (i,j),(j,i)算两次,但是 ( i , i ) (i,i) (i,i)算一次,所以原式转化为:
2 × ( ∑ i = 1 n ∑ j = 1 i i × σ 1 ( i j ) ) − ∑ i = 1 n i σ 1 ( i 2 ) 2\times\left(\sum_{i=1}^n\sum_{j=1}^ii\times \sigma_1(ij)\right)-\sum_{i=1}^ni\sigma_1(i^2) 2×(i=1∑nj=1∑ii×σ1(ij))−i=1∑niσ1(i2)
我们把它分成两部分分析:
一个是前半部分:
∑ i = 1 n ∑ j = 1 i i × σ 1 ( i j ) \sum_{i=1}^n\sum_{j=1}^ii\times \sigma_1(ij) i=1∑nj=1∑ii×σ1(ij)
根据这个题的经验,我们显然可以将后面的那一个 σ 1 ( i j ) \sigma_1(ij) σ1(ij)变换掉:
∑ i = 1 n ∑ j = 1 i i × σ 1 ( i j ) = ∑ i = 1 n ∑ j = 1 i i ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] x j y \begin{aligned} \sum_{i=1}^n\sum_{j=1}^ii\times \sigma_1(ij)=& \sum_{i=1}^n\sum_{j=1}^ii\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\frac{xj}{y} \end{aligned} i=1∑nj=1∑ii×σ1(ij)=i=1∑nj=1∑iix∣i∑y∣j∑[gcd(x,y)=1]yxj
然后大都是这个题的套路,我们作如下变换:
∑
i
=
1
n
∑
j
=
1
i
i
×
σ
1
(
i
j
)
=
∑
i
=
1
n
∑
j
=
1
i
i
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
y
)
=
1
]
x
j
y
=
∑
i
=
1
n
i
∑
j
=
1
i
∑
x
∣
i
∑
y
∣
j
x
j
y
∑
w
∣
x
,
w
∣
y
μ
(
w
)
=
∑
w
=
1
n
μ
(
w
)
∑
w
∣
x
x
∑
x
∣
i
i
∑
w
∣
y
∑
y
∣
j
j
y
=
∑
w
=
1
n
μ
(
w
)
∑
x
=
1
⌊
n
w
⌋
x
w
∑
x
∣
i
i
w
∑
y
=
1
⌊
n
w
⌋
∑
y
∣
j
j
w
y
w
=
∑
w
=
1
n
μ
(
w
)
w
2
∑
x
=
1
⌊
n
w
⌋
x
∑
x
∣
i
i
∑
y
=
1
⌊
n
w
⌋
∑
y
∣
j
j
y
=
∑
w
=
1
n
μ
(
w
)
w
2
∑
i
=
1
⌊
n
w
⌋
i
∑
x
∣
i
x
∑
j
=
1
⌊
n
w
⌋
∑
y
∣
j
j
y
\begin{aligned} \sum_{i=1}^n\sum_{j=1}^ii\times \sigma_1(ij)=& \sum_{i=1}^n\sum_{j=1}^ii\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\frac{xj}{y} \\ =& \sum_{i=1}^ni\sum_{j=1}^i\sum_{x|i}\sum_{y|j}\frac{xj}{y}\sum_{w|x,w|y}\mu(w) \\ =& \sum_{w=1}^n\mu(w)\sum_{w|x}x\sum_{x|i}i\sum_{w|y}\sum_{y|j}\frac{j}{y} \\ =& \sum_{w=1}^n\mu(w)\sum_{x=1}^{\lfloor\frac{n}{w}\rfloor}xw\sum_{x|i}iw\sum_{y=1}^{\lfloor\frac{n}{w}\rfloor}\sum_{y|j}\frac{jw}{yw} \\ =& \sum_{w=1}^n\mu(w)w^2\sum_{x=1}^{\lfloor\frac{n}{w}\rfloor}x\sum_{x|i}i\sum_{y=1}^{\lfloor\frac{n}{w}\rfloor}\sum_{y|j}\frac{j}{y} \\ =& \sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sum_{x|i}x\sum_{j=1}^{\lfloor\frac{n}{w}\rfloor}\sum_{y|j}\frac{j}{y} \end{aligned}
i=1∑nj=1∑ii×σ1(ij)======i=1∑nj=1∑iix∣i∑y∣j∑[gcd(x,y)=1]yxji=1∑nij=1∑ix∣i∑y∣j∑yxjw∣x,w∣y∑μ(w)w=1∑nμ(w)w∣x∑xx∣i∑iw∣y∑y∣j∑yjw=1∑nμ(w)x=1∑⌊wn⌋xwx∣i∑iwy=1∑⌊wn⌋y∣j∑ywjww=1∑nμ(w)w2x=1∑⌊wn⌋xx∣i∑iy=1∑⌊wn⌋y∣j∑yjw=1∑nμ(w)w2i=1∑⌊wn⌋ix∣i∑xj=1∑⌊wn⌋y∣j∑yj
因为 ∑ y ∣ j j y = ∑ y ∣ j y \sum_{y|j}\frac{j}{y}=\sum_{y|j}y ∑y∣jyj=∑y∣jy,而根据在这个题目的技巧,我们知道 σ 1 ( j ) = ∑ y ∣ j y \sigma_1(j)=\sum_{y|j}y σ1(j)=∑y∣jy,所以上面继续可以变换为:
∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i ∑ x ∣ i x ∑ j = 1 ⌊ n w ⌋ ∑ y ∣ j j y = ∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i σ 1 ( i ) ∑ j = 1 ⌊ n w ⌋ σ 1 ( j ) \begin{aligned} \sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sum_{x|i}x\sum_{j=1}^{\lfloor\frac{n}{w}\rfloor}\sum_{y|j}\frac{j}{y}=& \sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sigma_1(i)\sum_{j=1}^{\lfloor\frac{n}{w}\rfloor}\sigma_1(j) \end{aligned} w=1∑nμ(w)w2i=1∑⌊wn⌋ix∣i∑xj=1∑⌊wn⌋y∣j∑yj=w=1∑nμ(w)w2i=1∑⌊wn⌋iσ1(i)j=1∑⌊wn⌋σ1(j)
然后我们可以 O ( n ) O(n) O(n)的筛出 σ 1 , μ \sigma_1,\mu σ1,μ,并预处理上面的所用到的前缀和。
一个是后半部分:
∑ i = 1 n i σ 1 ( i 2 ) \sum_{i=1}^ni\sigma_1(i^2) i=1∑niσ1(i2)
这个处理就和上面的十分类似了:
∑ i = 1 n i σ 1 ( i 2 ) = ∑ i = 1 n i ∑ x ∣ i ∑ y ∣ i [ g c d ( x , y ) = 1 ] i x y = ∑ i = 1 n i ∑ x ∣ i ∑ y ∣ i i x y ∑ w ∣ x , w ∣ y μ ( w ) = ∑ w = 1 n μ ( w ) ∑ w ∣ i i ∑ w ∣ x , x ∣ i x ∑ w ∣ y , y ∣ i i y = ∑ w = 1 n μ ( w ) ∑ i = 1 ⌊ n w ⌋ i w ∑ x ∣ i x w ∑ y ∣ i i w y w = ∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i ∑ x ∣ i x ∑ y ∣ i i y = ∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i σ 1 ( i ) σ 1 ( i ) = ∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i σ 1 2 ( i ) \begin{aligned} \sum_{i=1}^ni\sigma_1(i^2)=& \sum_{i=1}^ni\sum_{x|i}\sum_{y|i}[gcd(x,y)=1]\frac{ix}{y} \\ =& \sum_{i=1}^ni\sum_{x|i}\sum_{y|i}\frac{ix}{y}\sum_{w|x,w|y}\mu(w) \\ =& \sum_{w=1}^n\mu(w)\sum_{w|i}i\sum_{w|x,x|i}x\sum_{w|y,y|i}\frac{i}{y} \\ =& \sum_{w=1}^n\mu(w)\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}iw\sum_{x|i}xw\sum_{y|i}\frac{iw}{yw} \\ =& \sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sum_{x|i}x\sum_{y|i}\frac{i}{y} \\ =& \sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sigma_1(i)\sigma_1(i) \\ =& \sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sigma_1^2(i) \end{aligned} i=1∑niσ1(i2)=======i=1∑nix∣i∑y∣i∑[gcd(x,y)=1]yixi=1∑nix∣i∑y∣i∑yixw∣x,w∣y∑μ(w)w=1∑nμ(w)w∣i∑iw∣x,x∣i∑xw∣y,y∣i∑yiw=1∑nμ(w)i=1∑⌊wn⌋iwx∣i∑xwy∣i∑ywiww=1∑nμ(w)w2i=1∑⌊wn⌋ix∣i∑xy∣i∑yiw=1∑nμ(w)w2i=1∑⌊wn⌋iσ1(i)σ1(i)w=1∑nμ(w)w2i=1∑⌊wn⌋iσ12(i)
此时,我们可以同样的预处理,然后带入原式,每次数论分块,然后
O
(
n
)
O(\sqrt n)
O(n)的回答,复杂度大概
O
(
n
+
T
n
)
O(n+T\sqrt n)
O(n+Tn),但是最大数据有
1
0
6
+
2
×
50000
×
1000
10^6+2\times 50000\times 1000
106+2×50000×1000,差不多一亿左右,而且加上大常数,最大数据大概跑3s左右,虽然丧心病狂地卡卡常就能过,但是肯定还有更优秀的做法。
我们将上面的两个式子带回原式,作如下变换:
a n s ( n ) = 2 × ( ∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i σ 1 ( i ) ∑ j = 1 ⌊ n w ⌋ σ 1 ( j ) ) − ( ∑ w = 1 n μ ( w ) w 2 ∑ i = 1 ⌊ n w ⌋ i σ 1 2 ( i ) ) = ∑ w = 1 n μ ( w ) w 2 ( ∑ i = 1 ⌊ n w ⌋ ( 2 ⋅ i σ 1 ( i ) − i σ 1 2 ( i ) ) ∑ j = 1 ⌊ n w ⌋ σ 1 ( j ) ) = ∑ w = 1 n μ ( w ) w 2 ( ∑ i = 1 ⌊ n w ⌋ i σ 1 ( i ) ( 2 ⋅ ∑ j = 1 ⌊ n w ⌋ σ 1 ( j ) − σ 1 ( i ) ) ) \begin{aligned} ans(n) =& 2\times\left(\sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sigma_1(i)\sum_{j=1}^{\lfloor\frac{n}{w}\rfloor}\sigma_1(j)\right)-\left(\sum_{w=1}^n\mu(w)w^2\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sigma_1^2(i)\right) \\ =& \sum_{w=1}^n\mu(w)w^2\left(\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}(2\cdot i\sigma_1(i)-i\sigma_1^2(i))\sum_{j=1}^{\lfloor\frac{n}{w}\rfloor}\sigma_1(j)\right) \\ =& \sum_{w=1}^n\mu(w)w^2\left(\sum_{i=1}^{\lfloor\frac{n}{w}\rfloor}i\sigma_1(i)\left(2\cdot \sum_{j=1}^{\lfloor\frac{n}{w}\rfloor}\sigma_1(j)-\sigma_1(i)\right)\right) \end{aligned} ans(n)===2×⎝⎛w=1∑nμ(w)w2i=1∑⌊wn⌋iσ1(i)j=1∑⌊wn⌋σ1(j)⎠⎞−⎝⎛w=1∑nμ(w)w2i=1∑⌊wn⌋iσ12(i)⎠⎞w=1∑nμ(w)w2⎝⎛i=1∑⌊wn⌋(2⋅iσ1(i)−iσ12(i))j=1∑⌊wn⌋σ1(j)⎠⎞w=1∑nμ(w)w2⎝⎛i=1∑⌊wn⌋iσ1(i)⎝⎛2⋅j=1∑⌊wn⌋σ1(j)−σ1(i)⎠⎞⎠⎞
如果我们能预处理处所有的 a n s ( n ) ans(n) ans(n),然后每次 O ( 1 ) O(1) O(1)的回答,那就会优秀的多,所以我们发现 a n s ( n ) ans(n) ans(n)不好直接求,所以考虑一个神奇的东西:差分
其实这个技巧在前面做过的题目中出现过:Imagine大佬-Orz,Imagine这个题目就用的差分做的。
我们来看,差分后如何计算:
c a n s ( n ) = a n s ( n ) − a n s ( n − 1 ) \begin{aligned} cans(n)=&ans(n)-ans(n-1) \end{aligned} cans(n)=ans(n)−ans(n−1)
直接算,发现并不好算QAQ,所以我们考虑对于一个单个的 n n n,那么定义它的贡献就为:
= ∑ d ∣ n μ ( d ) d 2 ( ( 2 ⋅ ∑ i = 1 ⌊ n d ⌋ σ 1 ( i ) − σ 1 ( ⌊ n d ⌋ ) ) ⋅ ⌊ n d ⌋ ⋅ σ 1 ( ⌊ n d ⌋ ) ) =\sum_{d|n}\mu(d)d^2\left(\left(2\cdot \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sigma_1(i)-\sigma_1(\lfloor\frac{n}{d}\rfloor)\right)\cdot \lfloor\frac{n}{d}\rfloor\cdot \sigma_1(\lfloor\frac{n}{d}\rfloor)\right) =d∣n∑μ(d)d2⎝⎛⎝⎛2⋅i=1∑⌊dn⌋σ1(i)−σ1(⌊dn⌋)⎠⎞⋅⌊dn⌋⋅σ1(⌊dn⌋)⎠⎞
其实这里的意思,对于每一个 c a n s ( n ) cans(n) cans(n),对其进行贡献的有它的因子 d d d,然后带入上面的式子可以得到这个。
而 a n s ( n ) ans(n) ans(n),就是 c a n s ( 1 ∼ n ) cans(1\sim n) cans(1∼n)所有的贡献,所以我们此时再求出 c a n s cans cans的前缀和就是 a n s ans ans了。
也就是我们将一个前缀和中的一些项拆了出来,而两个前缀和之间差的就是 n n n的贡献,所以差分的 c a n s cans cans就等于这个。
而上面的那个 c a n s cans cans的预处理,我们用类似埃氏筛,枚举因子倍数 O ( n l o g n ) O(nlogn) O(nlogn)的预处理即可。
所以总的复杂度变成了 O ( n l o g n + T ) O(nlogn+T) O(nlogn+T),就不卡常啦!代码还是比较好写。
51Nod官网上还有一种不同的题解,方法差不多但是又有很多不同的技巧,有兴趣的可以去官网看。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e6+10,N=1e5+10,MAX=1e6+1;
const ll Mod=1e9+7;
ll prime[N],sigma[M],mu[M],c[M],cnt,ans[M];
bool vis[M];
void init(){
mu[1]=sigma[1]=1;
for(ll i=2;i<MAX;i++){
if(!vis[i]){
prime[++cnt]=i;
mu[i]=-1;
sigma[i]=1+i;
c[i]=1+i;
}
for(ll j=1,v;j<=cnt&&i*prime[j]<MAX;j++){
v=i*prime[j];
vis[v]=1;
if(!(i%prime[j])){
c[v]=c[i]*prime[j]+1;
sigma[v]=sigma[i]/c[i]*c[v];
break;
}
mu[v]=-mu[i];
sigma[v]=sigma[i]*sigma[prime[j]];
c[v]=prime[j]+1;
}
}
ll sum=1;
for(ll i=2;i<MAX;i++){
sum=(sum+sigma[i])%Mod;
sigma[i]=(i*sigma[i]%Mod*((2ll*sum-sigma[i])%Mod)%Mod)%Mod;
if(sigma[i]<0)sigma[i]+=Mod;
}
for(ll i=1,v;i<MAX;i++){
v=((i*i)%Mod*mu[i])%Mod;
if(v<0)v+=Mod;
for(ll j=1;i*j<MAX;j++){
ans[i*j]=(ans[i*j]+v*sigma[j]%Mod)%Mod;
}
}
for(ll i=2;i<MAX;i++)ans[i]=(ans[i-1]+ans[i])%Mod;
}
int T,n;
int main(){
init();
scanf("%d",&T);
for(int cas=1;cas<=T;cas++){
scanf("%d",&n);
printf("Case #%d: %lld\n",cas,ans[n]);
}
return 0;
}