前置知識:杜教篩。(不會點這裏 )。
大片公式預警!!!
題意
求∑ i = 1 n ∑ j = 1 n lcm ( i , j ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\text{lcm}(i,j) i = 1 ∑ n j = 1 ∑ n lcm ( i , j ) 。(1 ≤ n ≤ 1 0 10 1\leq n\leq 10^{10} 1 ≤ n ≤ 1 0 1 0 )
題解
簡單回顧
開始之前,先來回顧一下幾個和杜教篩有關的式子(定義∗ * ∗ 爲數論函數的狄利克雷卷積):
I ( n ) = 1 , i d ( n ) = n , ϵ ( n ) = [ n = 1 ] μ ∗ I = ϵ ( 1 ) φ ∗ I = i d ( 2 ) μ ∗ i d = φ ( 3 )
\begin{aligned}&I(n)=1, \quad id(n)=n, \quad\epsilon(n)=[n=1]\\&\mu*I=\epsilon \qquad (1) \\&\varphi*I=id \qquad (2)\\&\mu*id=\varphi \qquad (3)\\\end{aligned}
I ( n ) = 1 , i d ( n ) = n , ϵ ( n ) = [ n = 1 ] μ ∗ I = ϵ ( 1 ) φ ∗ I = i d ( 2 ) μ ∗ i d = φ ( 3 )
由( 1 ) (1) ( 1 ) 可以推出∑ d ∣ n μ ( d ) = [ n = 1 ] \sum\limits_{d|n}\mu(d)=[n=1] d ∣ n ∑ μ ( d ) = [ n = 1 ] 。
由( 2 ) (2) ( 2 ) 可以推出∑ d ∣ n φ ( d ) = n \sum\limits_{d|n}\varphi(d)=n d ∣ n ∑ φ ( d ) = n 。
( 3 ) (3) ( 3 ) 則經常用於μ \mu μ 和φ \varphi φ 的互相轉化。
正式開始
看到這種題,上來就先暴力化式子。(除法默認下去整)
∑ i = 1 n ∑ j = 1 n lcm ( i , j ) = ∑ i = 1 n ∑ j = 1 n i j ( i , j ) = ∑ d = 1 n 1 d ∑ i = 1 n d ∑ j = 1 n d d 2 i j ⋅ [ ( i , j ) = d ] (先枚舉gcd) = ∑ d = 1 n d ∑ i = 1 n d ∑ j = 1 n d i j ∑ x ∣ ( i , j ) μ ( x ) (由(1)式可得) = ∑ d = 1 n d ∑ x = 1 n d x 2 μ ( x ) ∑ i = 1 n d x ∑ j = 1 n d x i j
\begin{aligned}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\text{lcm}(i,j)&=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\frac{ij}{(i,j)} \\&=\sum_{d=1}^{n}\frac{1}{d}\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}d^2ij\cdot[(i,j)=d] &\text{(先枚舉gcd)}\\&=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}ij\sum_{x|(i,j)}\mu(x) &\text{(由(1)式可得)}\\&=\sum_{d=1}^{n}d \sum_{x=1}^\frac{n}{d}x^2\mu(x) \sum_{i=1}^{\frac{n}{dx}}\sum_{j=1}^{\frac{n}{dx}}ij\end{aligned}
i = 1 ∑ n j = 1 ∑ n lcm ( i , j ) = i = 1 ∑ n j = 1 ∑ n ( i , j ) i j = d = 1 ∑ n d 1 i = 1 ∑ d n j = 1 ∑ d n d 2 i j ⋅ [ ( i , j ) = d ] = d = 1 ∑ n d i = 1 ∑ d n j = 1 ∑ d n i j x ∣ ( i , j ) ∑ μ ( x ) = d = 1 ∑ n d x = 1 ∑ d n x 2 μ ( x ) i = 1 ∑ d x n j = 1 ∑ d x n i j (先枚舉 gcd ) ( 由 (1) 式可得 )
接下來,設T = d x T=dx T = d x ,g ( x ) = ∑ i = 1 x ∑ j = 1 x i j = ( ∑ i = 1 x i ) 2 = n 2 ( n + 1 ) 2 4 g(x)=\sum\limits_{i=1}^{x}\sum\limits_{j=1}^{x}ij=(\sum\limits_{i=1}^{x}i)^2=\frac{n^2(n+1)^2}{4} g ( x ) = i = 1 ∑ x j = 1 ∑ x i j = ( i = 1 ∑ x i ) 2 = 4 n 2 ( n + 1 ) 2 。於是我們先枚舉T T T ,把g ( x ) g(x) g ( x ) 帶進去,就可以接着化上面那個式子了。
∑ d = 1 n d ∑ x = 1 n d x 2 μ ( x ) ∑ i = 1 n d x ∑ j = 1 n d x i j = ∑ T = 1 n g ( n T ) ∑ x ∣ T x 2 μ ( x ) ⋅ T x
\begin{aligned}\sum_{d=1}^{n}d \sum_{x=1}^\frac{n}{d}x^2\mu(x) \sum_{i=1}^{\frac{n}{dx}}\sum_{j=1}^{\frac{n}{dx}}ij&=\sum_{T=1}^{n}g(\frac{n}{T})\sum_{x|T}x^2\mu(x)\cdot\frac{T}{x}\end{aligned}
d = 1 ∑ n d x = 1 ∑ d n x 2 μ ( x ) i = 1 ∑ d x n j = 1 ∑ d x n i j = T = 1 ∑ n g ( T n ) x ∣ T ∑ x 2 μ ( x ) ⋅ x T
然後我們發現前面g ( n T ) g(\frac{n}{T}) g ( T n ) 可以除法分塊,關鍵在於如何求出後面這一部分的前綴和。
所以令F ( n ) = ∑ x ∣ n x 2 μ ( x ) ⋅ n x F(n)=\sum\limits_{x|n}x^2\mu(x)\cdot\frac{n}{x} F ( n ) = x ∣ n ∑ x 2 μ ( x ) ⋅ x n ,A ( n ) = n 2 μ ( n ) A(n)=n^2\mu(n) A ( n ) = n 2 μ ( n ) ,B ( n ) = n B(n)=n B ( n ) = n ,那麼F = A ∗ B F=A*B F = A ∗ B 。
B B B 看起來已經很簡單了,所以我們嘗試用構造一個C C C ,讓A ∗ C A*C A ∗ C 變得簡單一些,這樣就可以用杜教篩求前綴和了(很明顯F F F 是積性函數)。
我們發現A A A 中的x 2 x^2 x 2 讓我們很不舒服,所以我們考慮C ( x ) = x 2 C(x)=x^2 C ( x ) = x 2 ,這樣在卷積的時候可以把x 2 x^2 x 2 給消掉。
( A ∗ C ) ( n ) = ∑ x ∣ n x 2 μ ( x ) ( n x ) 2 = n 2 ∑ x ∣ n μ ( x ) = n 2 [ n = 1 ] (由之前的推論可得) = [ n = 1 ] ∴ A ∗ C = ϵ
\begin{aligned}(A*C)(n)&=\sum_{x|n}x^2\mu(x)(\frac{n}{x})^2\\&=n^2\sum_{x|n}\mu(x)\\&=n^2[n=1] &\text{(由之前的推論可得)}\\&=[n=1]\\\therefore A*C=\epsilon\end{aligned}
( A ∗ C ) ( n ) ∴ A ∗ C = ϵ = x ∣ n ∑ x 2 μ ( x ) ( x n ) 2 = n 2 x ∣ n ∑ μ ( x ) = n 2 [ n = 1 ] = [ n = 1 ] ( 由之前的推論可得 )
誒,這下看起來簡單多了。
∴ F ∗ C = ( A ∗ C ) ∗ B = ϵ ∗ B = B ∴ ( F ∗ C ) ( n ) = n
\begin{aligned}\therefore F*C&=(A*C)*B\\&=\epsilon*B\\&=B\\\therefore (F*C)&(n)=n\end{aligned}
∴ F ∗ C ∴ ( F ∗ C ) = ( A ∗ C ) ∗ B = ϵ ∗ B = B ( n ) = n
設S ( n ) S(n) S ( n ) 爲F ( n ) F(n) F ( n ) 的前綴和,然後套上杜教篩的式子:
C ( 1 ) S ( n ) = ∑ i = 1 n ( F ∗ C ) ( n ) − ∑ i = 2 n C ( i ) S ( n i ) 即 S ( n ) = n ( n + 1 ) 2 − ∑ i = 2 n i 2 S ( n i )
\begin{aligned}C(1)S(n)&=\sum_{i=1}^n(F*C)(n)-\sum_{i=2}^nC(i)S(\frac{n}{i})\\即\quad S(n)&=\frac{n(n+1)}{2}-\sum_{i=2}^{n}i^2S(\frac{n}{i})\end{aligned}
C ( 1 ) S ( n ) 即 S ( n ) = i = 1 ∑ n ( F ∗ C ) ( n ) − i = 2 ∑ n C ( i ) S ( i n ) = 2 n ( n + 1 ) − i = 2 ∑ n i 2 S ( i n )
那麼只要能夠線性求出前幾百萬個S S S 就可以直接杜教篩了。
觀察F ( n ) = ∑ x ∣ n x 2 μ ( x ) ⋅ n x = n ∑ x ∣ n x μ ( x ) F(n)=\sum\limits_{x|n}x^2\mu(x)\cdot\frac{n}{x}=n\sum\limits_{x|n}x\mu(x) F ( n ) = x ∣ n ∑ x 2 μ ( x ) ⋅ x n = n x ∣ n ∑ x μ ( x ) ,所以考慮線性篩出積性函數g ( n ) = ∑ x ∣ n x μ ( x ) g(n)=\sum\limits_{x|n}x\mu(x) g ( n ) = x ∣ n ∑ x μ ( x ) 。
我們想想線性篩的時候有那些情況需要考慮。
當n n n 爲質數時,g ( n ) = 1 ⋅ μ ( 1 ) + n ⋅ μ ( n ) = 1 − n g(n)=1\cdot \mu(1)+n\cdot \mu(n)=1-n g ( n ) = 1 ⋅ μ ( 1 ) + n ⋅ μ ( n ) = 1 − n 。
當p p p 爲質數且與i i i 互質時,g ( i ⋅ p ) = g ( i ) ⋅ g ( p ) = g ( i ) ⋅ ( 1 − p ) g(i\cdot p)=g(i)\cdot g(p)=g(i)\cdot (1-p) g ( i ⋅ p ) = g ( i ) ⋅ g ( p ) = g ( i ) ⋅ ( 1 − p ) 。
當p p p 爲質數且i i i 爲p的倍數時,由積性函數的性質可知,g ( i ) = g ( p 1 a 1 ) ⋅ g ( p 2 a 2 ) ⋯ g(i)=g(p_1^{a_1})\cdot g(p_2^{a_2})\cdots g ( i ) = g ( p 1 a 1 ) ⋅ g ( p 2 a 2 ) ⋯ ,那麼g ( i ⋅ p ) g(i\cdot p) g ( i ⋅ p ) 中,p p p 的指數至少是2,又因爲當指數a > 1 a>1 a > 1 時g ( p a ) = g ( p a − 1 ) + p a ⋅ μ ( p a ) = g ( p a − 1 ) g(p^a)=g(p^{a-1})+p^a\cdot \mu(p^a)=g(p^{a-1}) g ( p a ) = g ( p a − 1 ) + p a ⋅ μ ( p a ) = g ( p a − 1 ) ,則g ( p a ) = g ( p ) g(p^{a})=g(p) g ( p a ) = g ( p ) ,所以此時g ( i ⋅ p ) = g ( i ) g(i\cdot p)=g(i) g ( i ⋅ p ) = g ( i ) 。
考慮完這三種情況後,我們就可以線性篩出S S S 了。
代碼
#include <bits/stdc++.h>
#define ll long long
#define MAX 5000005
#define P 1000000007
using namespace std;
ll qpow ( ll a, ll n) {
ll res = 1 ;
while ( n) {
if ( n& 1 ) res = res* a% P;
a = a* a% P;
n >>= 1 ;
}
return res;
}
const ll inv2 = ( P+ 1 ) / 2 , inv6 = 166666668 ;
int cnt;
ll p[ MAX] , vis[ MAX] , f[ MAX] ;
void init ( int n) {
f[ 1 ] = 1 ;
for ( int i = 2 ; i <= n; i++ ) {
if ( ! vis[ i] ) {
p[ ++ cnt] = i;
f[ i] = 1 - i+ P;
}
for ( int j = 1 ; j <= cnt && p[ j] * i <= n; j++ ) {
vis[ p[ j] * i] = 1 ;
if ( i% p[ j] == 0 ) {
f[ i* p[ j] ] = f[ i] ;
break ;
}
f[ i* p[ j] ] = f[ i] * ( 1 - p[ j] + P) % P;
}
}
for ( int i = 1 ; i <= n; i++ ) {
f[ i] = ( f[ i] * i% P+ f[ i- 1 ] ) % P;
}
}
ll sum ( ll n) {
n % = P;
return n* ( n+ 1 ) % P* ( 2 * n% P+ 1 ) % P* inv6% P;
}
ll g ( ll n) {
n % = P;
return n* ( n+ 1 ) % P* n% P* ( n+ 1 ) % P* inv2% P* inv2% P;
}
map< ll, ll> s;
ll S ( ll n) {
if ( n < MAX) return f[ n] ;
if ( s. count ( n) ) return s[ n] ;
ll ans = ( n+ 1 ) % P* ( n% P) % P* inv2% P;
for ( ll l = 2 , r; l <= n; l = r+ 1 ) {
r = n/ ( n/ l) ;
( ans - = ( sum ( r) - sum ( l- 1 ) + P) % P* S ( n/ l) % P) % = P;
if ( ans < 0 ) ans + = P;
}
return s[ n] = ans% P;
}
int main ( )
{
init ( MAX- 1 ) ;
ll n, ans = 0 ;
cin >> n;
for ( ll l = 1 , r; l <= n; l = r+ 1 ) {
r = n/ ( n/ l) ;
ll t = n/ l, sum = ( S ( r) - S ( l- 1 ) + P) % P;
ans = ( ans+ g ( t) % P* sum% P) % P;
}
cout << ans << endl;
return 0 ;
}