莫比乌斯函数 
首先给出莫比乌斯函数 μ ( n ) \mu(n) μ ( n )   的定义:
n = ∏ i = 1 k p i c i μ ( n ) = { 0 , ∃ c i ≥ 2 ( − 1 ) k , ∀ c i < 2 n=\prod_{i=1}^k p_i^{c_i}\\
\mu(n)=\left \{
\begin{aligned}
&0,\exist c_i\ge 2\\
&(-1)^k,\forall c_i<2\\
\end{aligned}
\right.
 n = i = 1 ∏ k  p i c i   μ ( n ) = {  0 , ∃ c i  ≥ 2 ( − 1 ) k , ∀ c i  < 2  
特别地,n = 1 n=1 n = 1   时看作 k = 0 k=0 k = 0   因此 μ ( 1 ) = 1 \mu(1)=1 μ ( 1 ) = 1  。
性质 1 
莫比乌斯函数是积性函数,设 n , m n,m n , m   互质,它们的质因数分解形式为 ∏ i = 1 k p i c i \prod_{i=1}^k p_i^{c_i} ∏ i = 1 k  p i c i     与 ∏ j = 1 K P j C j \prod_{j=1}^K P_j^{C_j} ∏ j = 1 K  P j C j    ,那么:
μ ( n m ) = μ ( ∏ i = 1 k p i c i × ∏ j = 1 K P j C j ) \mu(nm)=\mu\left(\prod _{i=1}^k p_i^{c_i}\times \prod_{j=1}^KP_j^{C_j}\right)
 μ ( nm ) = μ ( i = 1 ∏ k  p i c i   × j = 1 ∏ K  P j C j   ) 
由于互质,所以对于任意 p i , P j p_i,P_j p i  , P j    都是互不相同的,因此:
μ ( ∏ i = 1 k p i c i × ∏ j = 1 K P j C j ) = { ( − 1 ) k + K = μ ( n ) μ ( m ) ∀ c i , C j < 2 0 = μ ( n ) μ ( m ) ∃ c i C j ≥ 2 \mu\left(\prod _{i=1}^k p_i^{c_i}\times \prod_{j=1}^KP_j^{C_j}\right)=\begin{cases}(-1)^{k+K}=\mu(n)\mu(m)\quad \forall c_i,C_j<2\\
0=\mu(n)\mu(m)\quad \exist c_iC_j\ge 2
\end{cases}
 μ ( i = 1 ∏ k  p i c i   × j = 1 ∏ K  P j C j   ) = { ( − 1 ) k + K = μ ( n ) μ ( m ) ∀ c i  , C j  < 2 0 = μ ( n ) μ ( m ) ∃ c i  C j  ≥ 2  
综上所述,μ ( n m ) = μ ( n ) μ ( m ) \mu(nm)=\mu(n)\mu(m) μ ( nm ) = μ ( n ) μ ( m )  ,这可用于线性筛预处理。
性质 2 
下面证明 ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum _{d\mid n}\mu(d)=[n=1] ∑ d ∣ n  μ ( d ) = [ n = 1 ]  :
当 n = 1 n=1 n = 1   时,结果显然成立,下面证明 n > 1 n>1 n > 1   时的情况,首先分解质因子:
n = ∏ i = 1 k p i c i , d = ∏ i = 1 k p i b i , ∀ b i ≤ c i n=\prod_{i=1}^{k}p_i^{c_i},d=\prod_{i=1}^{k}p_i^{b_i},\forall b_i\le c_i
 n = i = 1 ∏ k  p i c i   , d = i = 1 ∏ k  p i b i   , ∀ b i  ≤ c i  
当任意 b i > 1 b_i>1 b i  > 1   时,μ ( d ) = 0 \mu(d)=0 μ ( d ) = 0  ,所以不用考虑这种情况,因此就是从 k k k   个质因子中选几个进行求和的问题了。
∑ d ∣ n μ ( d ) = ( k 0 ) ( − 1 ) 0 + ( k 1 ) ( − 1 ) 1 + ⋯ + ( k k ) ( − 1 ) k = ( − 1 + 1 ) k = 0 \begin{aligned}
\sum_{d\mid n}\mu(d)&=\binom{k}{0}(-1)^0+\binom{k}{1}(-1)^1+\cdots+\binom{k}{k}(-1)^k\\
&=(-1+1)^k\\
&=0
\end{aligned}
 d ∣ n ∑  μ ( d )  = ( 0 k  ) ( − 1 ) 0 + ( 1 k  ) ( − 1 ) 1 + ⋯ + ( k k  ) ( − 1 ) k = ( − 1 + 1 ) k = 0  
基本上莫比乌斯反演的题目都是可以用 [ n = 1 ] [n=1] [ n = 1 ]   代换成莫比乌斯函数的求和,然后继续做下去的。
一个取整公式 
下面这个公式是成立的,并且是常用的。
⌊ a b c ⌋ = ⌊ ⌊ a / b ⌋ c ⌋ \lfloor\frac{a}{bc}\rfloor = \lfloor\frac{\lfloor a/b\rfloor }{c}\rfloor
 ⌊ b c a  ⌋ = ⌊ c ⌊ a / b ⌋  ⌋ 
证明:令 a = k b + r , k = q c + p a=kb+r,k=qc+p a = kb + r , k = q c + p  ,其中 r , p r,p r , p   分别是带余除法的余数,则有 r ∈ [ 0 , b − 1 ] , p ∈ [ 0 , c − 1 ] r\in[0,b-1],p\in[0,c-1] r ∈ [ 0 , b − 1 ] , p ∈ [ 0 , c − 1 ]  :
a = k b + r = q b c + p b + r ≤ q b c + b ( c − 1 ) + b − 1 = q b c + b c − 1 \begin{aligned}
a&=kb+r\\
&=qbc+pb+r\\
&\le qbc+b(c-1)+b-1\\
&=qbc+bc-1
\end{aligned}
 a  = kb + r = q b c + p b + r ≤ q b c + b ( c − 1 ) + b − 1 = q b c + b c − 1  
根据定义,⌊ a / b ⌋ = k , ⌊ k / c ⌋ = q \lfloor a/b\rfloor=k,\lfloor k/c\rfloor=q ⌊ a / b ⌋ = k , ⌊ k / c ⌋ = q  ,接下来求 ⌊ a / ( b c ) ⌋ \lfloor a/(bc)\rfloor ⌊ a / ( b c )⌋   的范围:
a b c = q b c + p b + r b c = q + p b + r b c ≥ q a b c ≤ b c ( q + 1 ) − 1 b c = q + 1 − 1 b c < q + 1 \begin{aligned}
\frac{a}{bc}&=\frac{qbc+pb+r}{bc}\\
&=q+\frac{pb+r}{bc}\\
&\ge q\\
\frac{a}{bc}&\le \frac{bc(q+1)-1}{bc}\\
&= q+1-\frac{1}{bc}\\
&\lt q+1\\
\end{aligned}
 b c a  b c a   = b c q b c + p b + r  = q + b c p b + r  ≥ q ≤ b c b c ( q + 1 ) − 1  = q + 1 − b c 1  < q + 1  
所以 ⌊ a / ( b c ) ⌋ = q \lfloor a/(bc)\rfloor = q ⌊ a / ( b c )⌋ = q  ,原文链接 在这里。
YY 的 GCD 
给定 T = 1 0 4 T=10^4 T = 1 0 4   组询问,每组给正整数 n , m n,m n , m   求 1 ≤ x ≤ n , 1 ≤ y ≤ m 1\le x\le n,1\le y\le m 1 ≤ x ≤ n , 1 ≤ y ≤ m   且 gcd  ( x , y ) \gcd(x,y) g cd( x , y )   为质数的 ( x , y ) (x,y) ( x , y )   有多少对,其中 1 ≤ n , m ≤ 1 0 7 1\le n,m\le 10^7 1 ≤ n , m ≤ 1 0 7  。
题目链接:P2257 。
 
题目对于 x , y x,y x , y   具有对称性,所以不妨设 n ≥ m n\ge m n ≥ m  ,首先写出要求的表达式:
∑ i = 1 n ∑ j = 1 m [ gcd  ( i , j ) ∈ Primes ] = ∑ p ∈ Primes ∑ i = 1 n ∑ j = 1 m [ gcd  ( i , j ) = p ] = ∑ p ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ [ gcd  ( i , j ) = 1 ] \begin{aligned}
\sum_{i=1}^{n}\sum_{j=1}^m[\gcd(i,j)\in \texttt{Primes}]&=\sum_{p\in \texttt{Primes}}\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=p]\\
&=\sum_{p}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[\gcd(i,j)=1]\\
\end{aligned}
 i = 1 ∑ n  j = 1 ∑ m  [ g cd( i , j ) ∈ Primes ]  = p ∈ Primes ∑  i = 1 ∑ n  j = 1 ∑ m  [ g cd( i , j ) = p ] = p ∑  i = 1 ∑ ⌊ p n  ⌋  j = 1 ∑ ⌊ p m  ⌋  [ g cd( i , j ) = 1 ]  
这里用到 ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum_{d\mid n}\mu(d)=[n=1] ∑ d ∣ n  μ ( d ) = [ n = 1 ]  ,继续化简:
∑ p ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ∑ d ∣ gcd  ( i , j ) μ ( d ) = ∑ p ∑ d = 1 ⌊ n p ⌋ ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ [ d ∣ i ] [ d ∣ j ] μ ( d ) = ∑ p ∑ d = 1 ⌊ n p ⌋ μ ( d ) ⌊ n p d ⌋ ⌊ m p d ⌋ \begin{aligned}
\sum_{p}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}\sum_{d\mid \gcd(i,j)}\mu(d)&=\sum_p\sum_{d=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[d\mid i][d\mid j]\mu(d)\\
&=\sum_p\sum_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\lfloor\frac{n}{pd}\rfloor\lfloor\frac{m}{pd}\rfloor
\end{aligned}
 p ∑  i = 1 ∑ ⌊ p n  ⌋  j = 1 ∑ ⌊ p m  ⌋  d ∣ g c d ( i , j ) ∑  μ ( d )  = p ∑  d = 1 ∑ ⌊ p n  ⌋  i = 1 ∑ ⌊ p n  ⌋  j = 1 ∑ ⌊ p m  ⌋  [ d ∣ i ] [ d ∣ j ] μ ( d ) = p ∑  d = 1 ∑ ⌊ p n  ⌋  μ ( d ) ⌊ p d n  ⌋ ⌊ p d m  ⌋  
发现这样做是无法通过本题的,目前复杂度为 O ( T ∑ p ⌊ n / p ⌋ ) = O ( T n ln  ln  n ) O(T\sum_p \lfloor n/p\rfloor)=O(Tn\ln\ln n) O ( T ∑ p  ⌊ n / p ⌋) = O ( T n ln ln n )  ,然后考虑怎么样对某些式子进行预处理。
要想把关于 n , m n,m n , m   的式子提出来,只有枚举 p d pd p d   的取值可以做到,令 k = p d k=pd k = p d  ,枚举 k k k  ,得到:
∑ k = 1 m ⌊ n k ⌋ ⌊ m k ⌋ ∑ p ∣ k μ ( k p ) \sum_{k=1}^m\lfloor\frac{n}{k}\rfloor\lfloor\frac{m}{k}\rfloor\sum_{p\mid k}\mu(\frac{k}{p})
 k = 1 ∑ m  ⌊ k n  ⌋ ⌊ k m  ⌋ p ∣ k ∑  μ ( p k  ) 
令 f ( k ) = ∑ p ∣ k μ ( k p ) f(k)=\sum_{p\mid k}\mu(\frac{k}{p}) f ( k ) = ∑ p ∣ k  μ ( p k  )  ,发现 f ( k ) f(k) f ( k )   与 n , m n,m n , m   无关,可以预处理,具体方法是枚举素数 p p p   的倍数,到 n n n   为止,这样复杂度应当是 O ( ∑ p ⌊ n / p ⌋ ) = O ( n ln  ln  n ) O(\sum_p \lfloor n/p\rfloor)=O(n\ln \ln n) O ( ∑ p  ⌊ n / p ⌋) = O ( n ln ln n )  ,可以接受。线性筛是 O ( n ) O(n) O ( n )  ,剩下就是一个整除分块了,这样总复杂度为 O ( n ln  ln  n + T n ) O(n\ln\ln n+T\sqrt n) O ( n ln ln n + T n  )  ,可以通过本题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include  <bits/stdc++.h>  using  namespace  std;#define  int long long const  int  N = 10000010 ;int  T, n, m, primes[N], mu[N], f[N], cntp;bitset<N> st; void  init (int  n)   {    mu[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         if  (!st[i]) primes[cntp++] = i, mu[i] = -1 ;         for  (int  j = 0 ; primes[j] <= n/i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) mu[i * primes[j]] = -mu[i];             else  {                 mu[i * primes[j]] = 0 ;                 break ;             }         }     }     for  (int  i = 0 ; i < cntp; i++)         for  (int  j = 1 ; j <= n / primes[i]; j++)             f[j * primes[i]] += mu[j];     for  (int  i = 1 ; i <= n; i++) f[i] += f[i-1 ]; } signed  main ()   {    init (N-1 );     cin >> T;     while  (T--) {         cin >> n >> m;         if  (n < m) swap (n, m);         int  k = 1 , res = 0 ;         while  (k <= m) {             int  nxt = min (n / (n / k), m / (m / k));             if  (nxt <= m) res += 1ll  * (n / k) * (m / k) * (f[nxt] - f[k-1 ]);             else  res += 1ll  * (n / k) * (m / k) * (f[m] - f[k-1 ]);             k = nxt + 1 ;         }         cout << res << endl;     }     return  0 ; } 
 
[HAOI2011] Problem b 
对于给出的 n n n   个询问,每次求有多少个数对( x , y ) (x,y) ( x , y )  ,满足 a ≤ x ≤ b a≤x≤b a ≤ x ≤ b  ,c ≤ y ≤ d c≤y≤d c ≤ y ≤ d  ,且 gcd  ( x , y ) = k \gcd(x,y)=k g cd( x , y ) = k  。
其中 1 ≤ n , k ≤ 5 × 1 0 4 1\le n,k\le 5\times 10^4 1 ≤ n , k ≤ 5 × 1 0 4 
题目链接:AcWing 2702 ,P2522 。
 
首先用前缀和的思想,求 ( 1 , 1 ) (1,1) ( 1 , 1 )   到 ( n , m ) (n,m) ( n , m )   的数量,设 n ≤ m n\le m n ≤ m  :
S ( n , m ) = ∑ i = 1 n ∑ j = 1 m [ gcd  ( i , j ) = k ] = ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ [ gcd  ( i , j ) = 1 ] = ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ∑ d ∣ gcd  ( i , j ) μ ( d ) = ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ [ d ∣ i ] [ d ∣ j ] = ∑ d = 1 ⌊ n k ⌋ μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ \begin{aligned}
S(n,m)&=\sum_{i=1}^n\sum_{j=1}^{m}[\gcd(i,j)=k]\\
&=\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[\gcd(i,j)=1]\\
&=\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum_{d\mid \gcd(i,j)}\mu(d)\\
&=\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[d\mid i][d\mid j]\\
&=\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor
\end{aligned}
 S ( n , m )  = i = 1 ∑ n  j = 1 ∑ m  [ g cd( i , j ) = k ] = i = 1 ∑ ⌊ k n  ⌋  j = 1 ∑ ⌊ k m  ⌋  [ g cd( i , j ) = 1 ] = i = 1 ∑ ⌊ k n  ⌋  j = 1 ∑ ⌊ k m  ⌋  d ∣ g c d ( i , j ) ∑  μ ( d ) = d = 1 ∑ ⌊ k n  ⌋  μ ( d ) i = 1 ∑ ⌊ k n  ⌋  j = 1 ∑ ⌊ k m  ⌋  [ d ∣ i ] [ d ∣ j ] = d = 1 ∑ ⌊ k n  ⌋  μ ( d ) ⌊ k d n  ⌋ ⌊ k d m  ⌋  
所以答案为 S ( b , d ) − S ( b , c − 1 ) − S ( a − 1 , d ) + S ( a − 1 , c − 1 ) S(b,d)-S(b,c-1)-S(a-1,d)+S(a-1,c-1) S ( b , d ) − S ( b , c − 1 ) − S ( a − 1 , d ) + S ( a − 1 , c − 1 )  ,对于求 S S S   用数论分块可以做到 O ( n ) O(\sqrt n) O ( n  )  ,这样总复杂度为 O ( n n ) O(n\sqrt n) O ( n n  )  。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include  <bits/stdc++.h>  using  namespace  std;const  int  N = 50010 ;int  T, a, b, c, d, k, mu[N], primes[N], cntp;bitset<N> st; void  init (int  n)   {    mu[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         if  (!st[i]) primes[cntp++] = i, mu[i] = -1 ;         for  (int  j = 0 ; primes[j] <= n/i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) mu[i * primes[j]] = -mu[i];             else  {                 mu[i * primes[j]] = 0 ;                 break ;             }         }     }     for  (int  i = 1 ; i <= n; i++) mu[i] += mu[i-1 ]; } int  S (int  n, int  m)   {    n /= k, m /= k;     if  (n > m) swap (n, m);     int  d = 1 , res = 0 ;     while  (d <= n) {         int  nxt = min (n / (n / d), m / (m / d));         if  (nxt <= n) res += (mu[nxt] - mu[d-1 ]) * (n / d) * (m / d);         else  res += (mu[n] - mu[d-1 ]) * (n / d) * (m / d);         d = nxt + 1 ;     }     return  res; } int  main ()   {    init (N-1 );     cin >> T;     while  (T--) {         cin >> a >> b >> c >> d >> k;         cout << S (b, d) - S (b, c-1 ) - S (a-1 , d) + S (a-1 , c-1 ) << endl;     }     return  0 ; } 
 
[SDOI2014] 数表 
对于 n × m n\times m n × m   的数表,位置 ( i , j ) (i,j) ( i , j )   值是同时整除 i , j i,j i , j   的所有自然数之和。给定 q q q   组询问,每组询问给出 n , m , a n,m,a n , m , a   问 n × m n\times m n × m   的数表中所有不大于 a a a   的数字之和。其中 1 ≤ n , m ≤ 1 0 5 , 1 ≤ q ≤ 2 × 1 0 4 1\le n,m\le 10^5,1\le q\le 2\times 10^4 1 ≤ n , m ≤ 1 0 5 , 1 ≤ q ≤ 2 × 1 0 4  。
题目链接:P3312 。
 
对于表格中 ( i , j ) (i,j) ( i , j )   的值是 V i j = ∑ d ∣ gcd  ( i , j ) d = σ ( gcd  ( i , j ) ) V_{ij}=\sum_{d\mid \gcd(i,j)}d=\sigma\big(\gcd(i,j)\big) V ij  = ∑ d ∣ g c d ( i , j )  d = σ ( g cd( i , j ) )  ,其中 σ ( x ) \sigma(x) σ ( x )   表示 x x x   的约数之和。
式子对于 i , j i,j i , j   对称,不妨设 n ≥ m n\ge m n ≥ m  ,求的是:
∑ i = 1 n ∑ j = 1 m σ ( gcd  ( i , j ) ) = ∑ d = 1 m σ ( d ) ∑ i = 1 n ∑ j = 1 m [ gcd  ( i , j ) = d ] = ∑ d = 1 m σ ( d ) ∑ i = 1 n ∑ j = 1 m [ gcd  ( i d , j d ) = 1 ] = ∑ d = 1 m σ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ gcd  ( i , j ) = 1 ] = ∑ d = 1 m σ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ∑ x ∣ gcd  ( i , j ) μ ( x ) = ∑ d = 1 m σ ( d ) ∑ x = 1 ⌊ m d ⌋ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ x ∣ i ] [ x ∣ j ] μ ( x ) = ∑ d = 1 m σ ( d ) ∑ x = 1 ⌊ m d ⌋ ⌊ n x d ⌋ ⌊ m x d ⌋ μ ( x ) = ∑ t = 1 m ⌊ n t ⌋ ⌊ m t ⌋ ∑ d ∣ t σ ( d ) μ ( t d ) \begin{aligned}
\sum_{i=1}^n\sum_{j=1}^m \sigma\Big(\gcd(i,j)\Big)&=\sum_{d=1}^m\sigma(d)\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]\\
&=\sum_{d=1}^m\sigma(d)\sum_{i=1}^n\sum_{j=1}^m[\gcd(\frac{i}{d},\frac{j}{d})=1]\\
&=\sum_{d=1}^m\sigma(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1]\\
&=\sum_{d=1}^m\sigma(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{x\mid \gcd(i,j)}\mu(x)\\
&=\sum_{d=1}^m\sigma(d)\sum_{x=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[x\mid i][x\mid j]\mu(x)\\
&=\sum_{d=1}^m\sigma(d)\sum_{x=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{n}{xd}\rfloor\lfloor\frac{m}{xd}\rfloor\mu(x)\\
&=\sum_{t=1}^m\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\sum_{d\mid t}\sigma(d)\mu(\frac{t}{d})
\end{aligned}
 i = 1 ∑ n  j = 1 ∑ m  σ ( g cd( i , j ) )  = d = 1 ∑ m  σ ( d ) i = 1 ∑ n  j = 1 ∑ m  [ g cd( i , j ) = d ] = d = 1 ∑ m  σ ( d ) i = 1 ∑ n  j = 1 ∑ m  [ g cd( d i  , d j  ) = 1 ] = d = 1 ∑ m  σ ( d ) i = 1 ∑ ⌊ d n  ⌋  j = 1 ∑ ⌊ d m  ⌋  [ g cd( i , j ) = 1 ] = d = 1 ∑ m  σ ( d ) i = 1 ∑ ⌊ d n  ⌋  j = 1 ∑ ⌊ d m  ⌋  x ∣ g c d ( i , j ) ∑  μ ( x ) = d = 1 ∑ m  σ ( d ) x = 1 ∑ ⌊ d m  ⌋  i = 1 ∑ ⌊ d n  ⌋  j = 1 ∑ ⌊ d m  ⌋  [ x ∣ i ] [ x ∣ j ] μ ( x ) = d = 1 ∑ m  σ ( d ) x = 1 ∑ ⌊ d m  ⌋  ⌊ x d n  ⌋ ⌊ x d m  ⌋ μ ( x ) = t = 1 ∑ m  ⌊ t n  ⌋ ⌊ t m  ⌋ d ∣ t ∑  σ ( d ) μ ( d t  )  
令 F ( t ) = ∑ d ∣ t σ ( d ) μ ( t d ) F(t)=\sum_{d\mid t}\sigma(d)\mu(\frac{t}{d}) F ( t ) = ∑ d ∣ t  σ ( d ) μ ( d t  )  ,对于这个函数可以进行预处理,并且复杂度为 O ( ∑ d ⌊ n / d ⌋ ) = O ( n log  n ) O(\sum_{d}\lfloor n/d\rfloor)=O(n\log n) O ( ∑ d  ⌊ n / d ⌋) = O ( n log  n )  。对于 a a a  ,如果 a a a   是单调递增的,那么每次对于某些 F ( t ) F(t) F ( t )   值进行增加,所以可以离线下来排序并且用树状数组维护 F ( t ) F(t) F ( t )   的值。
这样预处理线性筛 + 约数之和的复杂度为 O ( n log  n ) O(n\log n) O ( n log  n )  ,修改 F ( t ) F(t) F ( t )   值的总复杂度为 O ( n log  2 n ) O(n\log^2n) O ( n log  2 n )  ,回答询问的复杂度是 O ( q n log  n ) O(q\sqrt n\log n) O ( q n  log  n )  ,并且树状数组的常数比较小,可以通过本题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include  <bits/stdc++.h>  using  namespace  std;#define  fi first #define  se second #define  lowbit(x) ((x)&(-x)) #define  int long long typedef  pair<int , int > PII;const  int  N = 100010 , Q = 20010 , P = 1ll  << 31 ;int  q, ans[Q], sigma[N], primes[N], mu[N], cntp;PII s1[N]; bitset<N> st; struct  BIT  {    int  tr[N];     void  add (int  p, int  k)   {         for  (; p < N; p += lowbit (p)) {             tr[p] = (tr[p] + k) % P;             if  (tr[p] < 0 ) tr[p] += P;         }     }     int  query (int  p)   {         int  res = 0 ;         for  (; p; p -= lowbit (p)) res = (res + tr[p]) % P;         return  res;     }     int  query (int  l, int  r)   {         int  res = (query (r) - query (l-1 )) % P;         if  (res < 0 ) res += P;         return  res;     } } F; struct  Query  {    int  id, n, m, a;     bool  operator <(const  Query& qry) const  {         return  a < qry.a;     } } qry[Q]; void  init (int  n)   {    mu[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         if  (!st[i]) primes[cntp++] = i, mu[i] = -1 ;         for  (int  j = 0 ; primes[j] <= n / i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) mu[i * primes[j]] = -mu[i];             else  {                 mu[i * primes[j]] = 0 ;                 break ;             }         }     }     for  (int  i = 1 ; i <= n; i++)         for  (int  j = i; j <= n; j += i)             sigma[j] += i;     for  (int  i = 1 ; i <= n; i++) s1[i] = {sigma[i], i};     sort (s1+1 , s1+1 +n); } signed  main ()   {    init (N-1 );     cin >> q;     for  (int  i = 1 , n, m, a; i <= q; i++) {         cin >> n >> m >> a;         if  (n < m) swap (n, m);         qry[i] = {i, n, m, a};     }     sort (qry+1 , qry+1 +q);     for  (int  i = 1 , j = 1 ; i <= q; i++) {         while  (j < N && s1[j].fi <= qry[i].a) {             int  d = s1[j].se;             for  (int  t = d; t <= N-1 ; t += d) F.add (t, sigma[d] * mu[t / d]);             j++;         }         int  res = 0 , t = 1 , n = qry[i].n, m = qry[i].m;         while  (t <= m) {             int  nxt = min (n / (n / t), m / (m / t));             if  (nxt <= m) res = (res + 1ll  * (m / t) * (n / t) * F.query (t, nxt)) % P;             else  res = (res + 1ll  * (m / t) * (n / t) * F.query (t, m)) % P;             t = nxt + 1 ;         }         ans[qry[i].id] = res;     }     for  (int  i = 1 ; i <= q; i++) cout << ans[i] << endl;     return  0 ; } 
 
[SDOI2017] 数字表格 
给定 T T T   组询问,每组询问给出 n , m n,m n , m   问:
∏ i = 1 n ∏ j = 1 m f ( gcd  ( i , j ) )   m o d   ( 1 0 9 + 7 ) \prod_{i=1}^n\prod_{j=1}^m f\Big(\gcd(i,j)\Big) \bmod (10^9+7)
 i = 1 ∏ n  j = 1 ∏ m  f ( g cd( i , j ) ) mod ( 1 0 9 + 7 ) 
其中 f ( n ) f(n) f ( n )   表示斐波那契数列的第 n n n   项,且 1 ≤ T ≤ 1 0 3 , 1 ≤ n , m ≤ 1 0 6 1\le T\le 10^3,1\le n,m\le 10^6 1 ≤ T ≤ 1 0 3 , 1 ≤ n , m ≤ 1 0 6  。
题目链接:P3704 。
 
其实这几个题都比较类似,不妨设 n ≥ m n\ge m n ≥ m  。
∏ i = 1 n ∏ j = 1 m f ( gcd  ( i , j ) ) = ∏ d = 1 m ∏ i = 1 n ∏ j = 1 m f ( d ) [ gcd  ( i , j ) = d ] = ∏ d = 1 m ( f ( d ) ) ∑ i = 1 ⌊ n / d ⌋ ∑ j = 1 ⌊ m / d ⌋ [ gcd  ( i , j ) = 1 ] = ∏ d = 1 m ( f ( d ) ) ∑ x = 1 ⌊ m / d ⌋ ⌊ n x d ⌋ ⌊ m x d ⌋ μ ( x ) = ∏ t = 1 m ∏ d ∣ t ( f ( d ) ) ⌊ n t ⌋ ⌊ m t ⌋ μ ( t d ) = ∏ t = 1 m ( ∏ d ∣ t ( f ( d ) ) μ ( t d ) ) ⌊ m t ⌋ ⌊ n t ⌋ = ∏ t = 1 m ( F ( t ) ) ⌊ n t ⌋ ⌊ m t ⌋ \begin{aligned}
\prod_{i=1}^n\prod_{j=1}^m f\Big(\gcd(i,j)\Big)&=\prod_{d=1}^m\prod_{i=1}^n\prod_{j=1}^mf(d)[\gcd(i,j)=d]\\
&=\prod_{d=1}^m\Big(f(d)\Big)^{\sum_{i=1}^{\lfloor n/d\rfloor}\sum_{j=1}^{\lfloor m/d\rfloor}[\gcd(i,j)=1]}\\
&=\prod_{d=1}^m\Big(f(d)\Big)^{\sum_{x=1}^{\lfloor m/d\rfloor}\lfloor\frac{n}{xd}\rfloor\lfloor\frac{m}{xd}\rfloor\mu(x)}\\
&=\prod_{t=1}^m\prod_{d\mid t}\Big(f(d)\Big)^{\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor\mu(\frac{t}{d})}\\
&=\prod_{t=1}^m\left(\prod_{d\mid t}\Big(f(d)\Big)^{\mu(\frac{t}{d})}\right)^{\lfloor\frac{m}{t}\rfloor\lfloor\frac{n}{t}\rfloor}\\
&=\prod_{t=1}^m\Big(F(t)\Big)^{\lfloor\frac{n}{t}\rfloor\lfloor\frac{m}{t}\rfloor}
\end{aligned}
 i = 1 ∏ n  j = 1 ∏ m  f ( g cd( i , j ) )  = d = 1 ∏ m  i = 1 ∏ n  j = 1 ∏ m  f ( d ) [ g cd( i , j ) = d ] = d = 1 ∏ m  ( f ( d ) ) ∑ i = 1 ⌊ n / d ⌋  ∑ j = 1 ⌊ m / d ⌋  [ g c d ( i , j ) = 1 ] = d = 1 ∏ m  ( f ( d ) ) ∑ x = 1 ⌊ m / d ⌋  ⌊ x d n  ⌋ ⌊ x d m  ⌋ μ ( x ) = t = 1 ∏ m  d ∣ t ∏  ( f ( d ) ) ⌊ t n  ⌋ ⌊ t m  ⌋ μ ( d t  ) = t = 1 ∏ m   d ∣ t ∏  ( f ( d ) ) μ ( d t  )  ⌊ t m  ⌋ ⌊ t n  ⌋ = t = 1 ∏ m  ( F ( t ) ) ⌊ t n  ⌋ ⌊ t m  ⌋  
其中 F ( t ) F(t) F ( t )   可以 O ( n log  n ) O(n\log n) O ( n log  n )   预处理,整除分块预处理 F ( t ) F(t) F ( t )   的前缀积即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include  <bits/stdc++.h>  using  namespace  std;#define  int long long const  int  N = 1000010 , P = 1e9 +7 ;int  n, m, T;int  F[N], f[N], mu[N], primes[N], cntp;bitset<N> st; int  qmi (int  a, int  k)   {    int  res = 1 ;     while  (k) {         if  (k & 1 ) res = res * a % P;         a = a * a % P;         k >>= 1 ;     }     return  res; } void  init (int  n)   {    mu[1 ] = 1 , f[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         f[i] = (f[i-1 ] + f[i-2 ]) % P;         if  (!st[i]) primes[cntp++] = i, mu[i] = -1 ;         for  (int  j = 0 ; primes[j] <= n / i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) mu[i * primes[j]] = -mu[i];             else  {                 mu[i * primes[j]] = 0 ;                 break ;             }         }     }     for  (int  i = 0 ; i <= n; i++) F[i] = 1 ;     for  (int  i = 1 ; i <= n; i++) {         for  (int  j = i; j <= n; j += i) {             if  (mu[j / i] == -1 ) F[j] = F[j] * qmi (f[i], P-2 ) % P;             else  if  (mu[j / i] == 1 ) F[j] = F[j] * f[i] % P;         }     }     for  (int  i = 1 ; i <= n; i++) F[i] = F[i-1 ] * F[i] % P; } signed  main ()   {    cin >> T;     init (N-1 );     while  (T--) {         cin >> n >> m;         if  (n < m) swap (n, m);         int  t = 1 , res = 1 ;         while  (t <= m) {             int  nxt = min (n / (n / t), m / (m / t));             if  (nxt <= m) res = res * qmi (F[nxt] * qmi (F[t-1 ], P-2 ) % P, (n / t) * (m / t) % (P-1 )) % P;             else  res = res * qmi (F[m] * qmi (F[t-1 ], P-2 ) % P, (n / t) * (m / t) % (P-1 )) % P;             t = nxt + 1 ;         }         cout << res << endl;     }     return  0 ; }  
 
[国家集训队] Crash 的数字表格 
给定正整数 n , m n,m n , m   求:
( ∑ i = 1 n ∑ j = 1 m lcm ( i , j ) )   m o d   20101009 \left(\sum_{i=1}^n\sum_{j=1}^m\text{lcm}(i,j)\right)\bmod 20101009
 ( i = 1 ∑ n  j = 1 ∑ m  lcm ( i , j ) ) mod 20101009 
其中 1 ≤ n , m ≤ 1 0 7 1\le n,m\le 10^7 1 ≤ n , m ≤ 1 0 7  。
题目链接:P1829 。
 
首先 lcm ( i , j ) = i j / gcd  ( i , j ) \text{lcm}(i,j)=ij/\gcd(i,j) lcm ( i , j ) = ij / g cd( i , j )  ,假设 n ≥ m n\ge m n ≥ m  ,设 S ( n ) = ∑ i = 1 n i S(n)=\sum_{i=1}^n i S ( n ) = ∑ i = 1 n  i  ,有:
∑ i = 1 n ∑ j = 1 m lcm ( i , j ) = ∑ i = 1 n ∑ j = 1 m i j gcd  ( i , j ) = ∑ d = 1 m 1 d ∑ i = 1 n ∑ j = 1 m i j [ gcd  ( i , j ) = d ] = ∑ d = 1 m 1 d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j d 2 [ gcd  ( i , j ) = 1 ] = ∑ d = 1 m d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j ∑ x ∣ gcd  ( i , j ) μ ( x ) = ∑ d = 1 m d ∑ x = 1 m ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j μ ( x ) [ x ∣ i ] [ x ∣ j ] = ∑ d = 1 m d ∑ x = 1 m x 2 μ ( x ) ∑ i = 1 ⌊ n x d ⌋ ∑ j = 1 ⌊ m x d ⌋ i j = ∑ d = 1 m d ∑ x = 1 m x 2 μ ( x ) S ( ⌊ m x d ⌋ ) S ( ⌊ n x d ⌋ ) = ∑ t = 1 m t S ( ⌊ n t ⌋ ) S ( ⌊ m t ⌋ ) ∑ d ∣ t t d μ ( t d ) = ∑ t = 1 m t S ( ⌊ n t ⌋ ) S ( ⌊ m t ⌋ ) ∑ d ∣ t d μ ( d ) \begin{aligned}
\sum_{i=1}^n\sum_{j=1}^m \text{lcm}(i,j)&=\sum_{i=1}^n\sum_{j=1}^m \frac{ij}{\gcd(i,j)}\\
&=\sum_{d=1}^m\frac{1}{d}\sum_{i=1}^n\sum_{j=1}^mij[\gcd(i,j)=d]\\
&=\sum_{d=1}^m\frac{1}{d}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}ijd^2[\gcd(i,j)=1]\\
&=\sum_{d=1}^m d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}ij\sum_{x\mid \gcd(i,j)}\mu(x)\\
&=\sum_{d=1}^md\sum_{x=1}^m\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor} ij\mu(x)[x\mid i][x\mid j]\\
&=\sum_{d=1}^md\sum_{x=1}^mx^2\mu(x)\sum_{i=1}^{\lfloor\frac{n}{xd}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{xd}\rfloor}ij\\
&=\sum_{d=1}^md\sum_{x=1}^mx^2\mu(x)S(\lfloor\frac{m}{xd}\rfloor)S(\lfloor\frac{n}{xd}\rfloor)\\
&=\sum_{t=1}^mtS(\lfloor\frac{n}{t}\rfloor)S(\lfloor\frac{m}{t}\rfloor)\sum_{d\mid t}\frac{t}{d}\mu(\frac{t}{d})\\
&=\sum_{t=1}^mtS(\lfloor\frac{n}{t}\rfloor)S(\lfloor\frac{m}{t}\rfloor)\sum_{d\mid t}d\mu(d)\\
\end{aligned}
 i = 1 ∑ n  j = 1 ∑ m  lcm ( i , j )  = i = 1 ∑ n  j = 1 ∑ m  g cd( i , j ) ij  = d = 1 ∑ m  d 1  i = 1 ∑ n  j = 1 ∑ m  ij [ g cd( i , j ) = d ] = d = 1 ∑ m  d 1  i = 1 ∑ ⌊ d n  ⌋  j = 1 ∑ ⌊ d m  ⌋  ij d 2 [ g cd( i , j ) = 1 ] = d = 1 ∑ m  d i = 1 ∑ ⌊ d n  ⌋  j = 1 ∑ ⌊ d m  ⌋  ij x ∣ g c d ( i , j ) ∑  μ ( x ) = d = 1 ∑ m  d x = 1 ∑ m  i = 1 ∑ ⌊ d n  ⌋  j = 1 ∑ ⌊ d m  ⌋  ij μ ( x ) [ x ∣ i ] [ x ∣ j ] = d = 1 ∑ m  d x = 1 ∑ m  x 2 μ ( x ) i = 1 ∑ ⌊ x d n  ⌋  j = 1 ∑ ⌊ x d m  ⌋  ij = d = 1 ∑ m  d x = 1 ∑ m  x 2 μ ( x ) S (⌊ x d m  ⌋) S (⌊ x d n  ⌋) = t = 1 ∑ m  tS (⌊ t n  ⌋) S (⌊ t m  ⌋) d ∣ t ∑  d t  μ ( d t  ) = t = 1 ∑ m  tS (⌊ t n  ⌋) S (⌊ t m  ⌋) d ∣ t ∑  d μ ( d )  
实测小常数的 O ( n log  n ) O(n\log n) O ( n log  n )   是可以通过的,但是针对这个数据范围需要尽量写一个线性的。
设 f ( n ) = ∑ d ∣ n d μ ( d ) f(n)=\sum_{d\mid n}d\mu(d) f ( n ) = ∑ d ∣ n  d μ ( d )  ,显然 f ( 1 ) = 1 f(1)=1 f ( 1 ) = 1  ,看能否在线性筛中递推:
若 p p p   为质数,有 f ( p ) = 1 μ ( 1 ) + p μ ( p ) = 1 − p f(p)=1\mu(1)+p\mu(p)=1-p f ( p ) = 1 μ ( 1 ) + p μ ( p ) = 1 − p   成立。
 
若 p p p   小于 n n n   的最小质因子,那么对于任意 d ∣ n d\mid n d ∣ n  ,有 p d ∣ p n pd\mid pn p d ∣ p n   且 p d ∤ n pd\not\mid n p d  ∣ n  ,因此:
f ( p n ) = ∑ d ∣ n d μ ( d ) + ∑ d ∣ n p d μ ( p d ) = ∑ d ∣ n d μ ( d ) − p ∑ d ∣ n d μ ( d ) = ( 1 − p ) f ( n ) \begin{aligned}
f(pn)&=\sum_{d\mid n}d\mu(d)+\sum_{d\mid n} pd\mu(pd)\\
&=\sum_{d\mid n}d\mu(d)-p\sum_{d\mid n} d\mu(d)\\
&=(1-p)f(n)
\end{aligned}
 f ( p n )  = d ∣ n ∑  d μ ( d ) + d ∣ n ∑  p d μ ( p d ) = d ∣ n ∑  d μ ( d ) − p d ∣ n ∑  d μ ( d ) = ( 1 − p ) f ( n )  
 
若 p p p   为 n n n   的最小质因子,这并不会造成更多的贡献,因为只有当 d d d   的质因数次数不超过 1 1 1   时才会对 f ( n ) f(n) f ( n )   造成贡献,而 p p p   本来就存在于 n n n  ,所以 f ( p n ) = f ( n ) f(pn)=f(n) f ( p n ) = f ( n )  。
 
 
所以就可以开始写了,甚至不需要数论分块,复杂度 O ( n ) O(n) O ( n )  。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include  <bits/stdc++.h>  using  namespace  std;const  int  N = 10000010 , P = 20101009 ;int  n, m, primes[N], f[N], cntp;bitset<N> st; void  init (int  n)   {    f[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         if  (!st[i]) primes[cntp++] = i, f[i] = 1 -i;         for  (int  j = 0 ; primes[j] <= n/i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) f[i * primes[j]] = (1  - primes[j]) * f[i];             else  {                 f[i * primes[j]] = f[i];                 break ;             }         }     } } int  S (int  n)   {    return  1ll  * (1  + n) * n / 2  % P; } int  main ()   {    cin >> n >> m;     if  (n < m) swap (n, m);     init (n);     int  res = 0 ;     for  (int  t = 1 ; t <= m; t++) res = (res + 1ll  * t * S (n / t) % P * S (m / t) % P * f[t]) % P;     if  (res < 0 ) res += P;     cout << res << endl;     return  0 ; } 
 
[湖北省队互测2014] 一个人的数论 
给定 n = ∏ i = 1 ω p i a i n=\prod_{i=1}^{\omega}p_i^{a_i} n = ∏ i = 1 ω  p i a i    ,设 f d ( n ) f_d(n) f d  ( n )   是小于 n n n   且与 n n n   互质的正整数的 d d d   次方之和。输出 f d ( n )   m o d   ( 1 0 9 + 7 ) f_d(n)\bmod (10^9+7) f d  ( n ) mod ( 1 0 9 + 7 )  。
数据范围:0 ≤ d ≤ 100 , 1 ≤ ω ≤ 1 0 3 , 2 ≤ p i , a i ≤ 1 0 9 0\le d\le 100,1\le \omega\le 10^3,2\le p_i,a_i\le 10^9 0 ≤ d ≤ 100 , 1 ≤ ω ≤ 1 0 3 , 2 ≤ p i  , a i  ≤ 1 0 9  。
题目链接:P6271 。
 
对于 S ( n ) = ∑ i = 1 n i d S(n)=\sum_{i=1}^n i^d S ( n ) = ∑ i = 1 n  i d   是一个 d + 1 d+1 d + 1   次方的多项式,且常数项为 0 0 0  。设系数为 s 1 ∼ s d + 1 s_1\sim s_{d+1} s 1  ∼ s d + 1   ,这个可以高斯消元在 O ( d 3 ) O(d^3) O ( d 3 )   求解。
接下来化简式子:
f d ( n ) = ∑ i = 1 n i d [ gcd  ( i , n ) = 1 ] = ∑ i = 1 n i d ∑ x ∣ gcd  ( i , n ) μ ( x ) = ∑ x ∣ n ∑ i = 1 n [ x ∣ i ] i d μ ( x ) = ∑ x ∣ n x d μ ( x ) ∑ i = 1 n x i d = ∑ x ∣ n x d μ ( x ) S ( n x ) \begin{aligned}
f_d(n)&=\sum_{i=1}^ni^d[\gcd(i,n)=1]\\
&=\sum_{i=1}^ni^d\sum_{x\mid \gcd(i,n)}\mu(x)\\
&=\sum_{x\mid n}\sum_{i=1}^n[x\mid i]i^d\mu(x)\\
&=\sum_{x\mid n}x^d\mu(x)\sum_{i=1}^{\frac{n}{x}}i^d\\
&=\sum_{x\mid n}x^d\mu(x)S(\frac{n}{x})\\
\end{aligned}
 f d  ( n )  = i = 1 ∑ n  i d [ g cd( i , n ) = 1 ] = i = 1 ∑ n  i d x ∣ g c d ( i , n ) ∑  μ ( x ) = x ∣ n ∑  i = 1 ∑ n  [ x ∣ i ] i d μ ( x ) = x ∣ n ∑  x d μ ( x ) i = 1 ∑ x n   i d = x ∣ n ∑  x d μ ( x ) S ( x n  )  
上面说过 S ( n ) S(n) S ( n )   是一个 d + 1 d+1 d + 1   次的多项式,所以把它写成多项式的形式:
f d ( n ) = ∑ i = 1 d + 1 ∑ x ∣ n s i ( n x ) i x d μ ( x ) = ∑ i = 1 d + 1 ∑ x ∣ n s i n i x d − i μ ( x ) = ∑ i = 1 d + 1 s i n i ∑ x ∣ n x d − i μ ( x ) \begin{aligned}
f_d(n)&=\sum_{i=1}^{d+1}\sum_{x\mid n} s_i\left(\frac{n}{x}\right)^ix^d\mu(x)\\
&=\sum_{i=1}^{d+1}\sum_{x\mid n} s_in^ix^{d-i}\mu(x)\\
&=\sum_{i=1}^{d+1}s_in^i\sum_{x\mid n}x^{d-i}\mu(x)
\end{aligned}
 f d  ( n )  = i = 1 ∑ d + 1  x ∣ n ∑  s i  ( x n  ) i x d μ ( x ) = i = 1 ∑ d + 1  x ∣ n ∑  s i  n i x d − i μ ( x ) = i = 1 ∑ d + 1  s i  n i x ∣ n ∑  x d − i μ ( x )  
设 F i ( n ) = ∑ x ∣ n x d − i μ ( x ) F_i(n)=\sum_{x\mid n} x^{d-i}\mu(x) F i  ( n ) = ∑ x ∣ n  x d − i μ ( x )  ,看是否能快速求出 F i ( n ) F_i(n) F i  ( n )  。先证明一下它是积性函数,设 m , n m,n m , n   互质,则:
F i ( n ) F i ( m ) = ( ∑ x ∣ n x d − i μ ( x ) ) ( ∑ y ∣ m y d − i μ ( y ) ) = ∑ x ∣ n ∑ y ∣ m ( x y ) d − i μ ( x ) μ ( y ) = ∑ ( x y ) ∣ ( m n ) ( x y ) d − i μ ( x y ) = F i ( n m ) \begin{aligned}
F_i(n)F_i(m)&=\left(\sum_{x\mid n}x^{d-i}\mu(x)\right)\left(\sum_{y\mid m}y^{d-i}\mu(y)\right)\\
&=\sum_{x\mid n}\sum_{y\mid m}(xy)^{d-i}\mu(x)\mu(y)\\
&=\sum_{(xy)\mid (mn)} (xy)^{d-i}\mu(xy)\\
&=F_i(nm)
\end{aligned}
 F i  ( n ) F i  ( m )  =  x ∣ n ∑  x d − i μ ( x )   y ∣ m ∑  y d − i μ ( y )  = x ∣ n ∑  y ∣ m ∑  ( x y ) d − i μ ( x ) μ ( y ) = ( x y ) ∣ ( mn ) ∑  ( x y ) d − i μ ( x y ) = F i  ( nm )  
且对于素数 p p p  ,有:
F i ( p c ) = ∑ j = 0 c ( p j ) d − i μ ( p j ) = 1 − p d − i \begin{aligned}
F_i(p^c)&=\sum_{j=0}^{c}(p^j)^{d-i}\mu(p^j)\\
&=1-p^{d-i}
\end{aligned}
 F i  ( p c )  = j = 0 ∑ c  ( p j ) d − i μ ( p j ) = 1 − p d − i  
不计快速幂,可以在 O ( ω ) O(\omega) O ( ω )   的复杂度求出 F i ( n ) F_i(n) F i  ( n )  ,所以最终的式子是:
f d ( n ) = ∑ i = 1 d + 1 s i n i F i ( n ) f_d(n)=\sum_{i=1}^{d+1}s_in^iF_i(n)
 f d  ( n ) = i = 1 ∑ d + 1  s i  n i F i  ( n ) 
这样复杂度是 O ( d 3 + d ω ) O(d^3+d\omega) O ( d 3 + d ω )  ,可以接受。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include  <bits/stdc++.h>  using  namespace  std;#define  int long long const  int  D = 110 , W = 1010 , P = 1e9 +7 ;int  d, w, s[D], p[W], a[W], A[D][D];int  qmi (int  a, int  k)   {    int  res = 1 ;     while  (k) {         if  (k & 1 ) res = res * a % P;         a = a * a % P;         k >>= 1 ;     }     return  res; } void  gauss (int  n)   {    for  (int  p = 1 ; p <= n; p++) {         int  target = p;         for  (int  i = p+1 ; i <= n; i++) if  (A[i][p]) target = i;         for  (int  j = p; j <= n+1 ; j++) swap (A[p][j], A[target][j]);         int  inv = qmi (A[p][p], P-2 );         for  (int  j = p; j <= n+1 ; j++) A[p][j] = A[p][j] * inv % P;         for  (int  i = p+1 ; i <= n; i++)             for  (int  j = n+1 ; j >= p; j--) {                 A[i][j] = (A[i][j] - A[p][j] * A[i][p]) % P;                 if  (A[i][j] < 0 ) A[i][j] += P;             }     }     for  (int  i = n; i; i--) {         for  (int  j = i+1 ; j <= n; j++) {             A[i][n+1 ] = (A[i][n+1 ] - A[j][n+1 ] * A[i][j]) % P;             if  (A[i][n+1 ] < 0 ) A[i][n+1 ] += P;         }     }          for  (int  i = 1 ; i <= n; i++) s[i] = A[i][n+1 ]; } int  F (int  i)   {    int  res = 1 , power = d-i;     if  (power < 0 ) power += P-1 ;     for  (int  j = 1 ; j <= w; j++) {         res = res * (P + 1  - qmi (p[j], power)) % P;     }     return  res; } signed  main ()   {    cin >> d >> w;     for  (int  i = 1 ; i <= w; i++) cin >> p[i] >> a[i];     for  (int  i = 1 ; i <= d+1 ; i++) {                  for  (int  j = 0 , a = 1 ; j <= d+1 ; j++, a = a * i % P) A[i][j] = a;         A[i][d+2 ] = (A[i-1 ][d+2 ] + A[i][d]) % P;     }     gauss (d+1 );     int  res = 0 , n = 1 ;     for  (int  i = 1 ; i <= w; i++) n = n * qmi (p[i], a[i]) % P;     for  (int  i = 1 , ni = n; i <= d+1 ; i++, ni = ni * n % P) {         res = (res + s[i] * F (i) % P * ni) % P;     }     cout << res << endl;     return  0 ; } 
 
[CF803F] Coprime Subsequences 
给定长度为 n n n   的序列 a 1 , … , a n a_1,\dots,a_n a 1  , … , a n   ,问多少个子序列 T T T   满足 gcd  ( T ) = 1 \gcd(T)=1 g cd( T ) = 1  ,答案对 1 0 9 + 7 10^9+7 1 0 9 + 7   取模。其中 1 ≤ n , a i ≤ 1 0 5 1\le n,a_i\le 10^5 1 ≤ n , a i  ≤ 1 0 5  。
题目链接:CF803F 。
 
还是化简式子:
∑ T ⊂ S [ gcd  ( T ) = 1 ] = ∑ T ⊂ S ∑ d ∣ gcd  ( T ) μ ( d ) = ∑ d = 1 max  ( S ) ∑ d ∣ gcd  ( T ) μ ( d ) = ∑ d = 1 max  ( S ) μ ( d ) ( 2 ∑ i = 1 n [ d ∣ a i ] − 1 ) \begin{aligned}
\sum_{T\subset S}[\gcd(T)=1]&=\sum_{T\subset S}\sum_{d\mid \gcd(T)} \mu(d)\\
&=\sum_{d=1}^{\max(S)}\sum_{d\mid \gcd(T)} \mu(d)\\
&=\sum_{d=1}^{\max(S)}\mu(d)\left(2^{\sum_{i=1}^n [d\mid a_i]}-1\right)
\end{aligned}
 T ⊂ S ∑  [ g cd( T ) = 1 ]  = T ⊂ S ∑  d ∣ g c d ( T ) ∑  μ ( d ) = d = 1 ∑ m a x ( S )  d ∣ g c d ( T ) ∑  μ ( d ) = d = 1 ∑ m a x ( S )  μ ( d ) ( 2 ∑ i = 1 n  [ d ∣ a i  ] − 1 )  
所以枚举 d d d   再看它的倍数个数就行了,这样开一个桶来储存序列,复杂度是 O ( n log  n ) O(n\log n) O ( n log  n )  。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include  <bits/stdc++.h>  using  namespace  std;const  int  N = 100010 , P = 1e9 +7 ;int  n, mx, cnt[N], primes[N], mu[N], cntp;bitset<N> st; int  qmi (int  a, int  k)   {    int  res = 1 ;     while  (k) {         if  (k & 1 ) res = 1ll  * res * a % P;         a = 1ll  * a * a % P;         k >>= 1 ;     }     return  res; } void  init (int  n)   {    mu[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         if  (!st[i]) primes[cntp++] = i, mu[i] = -1 ;         for  (int  j = 0 ; primes[j] <= n / i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) mu[i * primes[j]] = -mu[i];             else  {                 mu[i * primes[j]] = 0 ;                 break ;             }         }     } } int  main ()   {    cin >> n;     for  (int  i = 1 , a; i <= n; i++) cin >> a, cnt[a]++, mx = max (mx, a);     init (mx);     int  res = 0 ;     for  (int  d = 1 ; d <= mx; d++) {         int  now = 0 ;         for  (int  nd = d; nd <= mx; nd += d) now += cnt[nd];         res = (res + 1ll  * mu[d] * (qmi (2 , now) - 1 )) % P;         if  (res < 0 ) res += P;     }     cout << res << endl;     return  0 ; } 
 
进一步地,可以对这个题进行拓展,求满足 gcd  ( T ) × len  ( T ) = k \gcd(T)\times \operatorname{len}(T)=k g cd( T ) × len ( T ) = k   的字序列个数,其中 1 ≤ n , a i , k ≤ 5 × 1 0 5 1\le n,a_i,k\le 5\times 10^5 1 ≤ n , a i  , k ≤ 5 × 1 0 5  。
思路是首先要枚举最大公约数 t t t  ,然后化简式子:
∑ t ∣ k ∑ T ⊂ S , len  ( T ) = k / t [ gcd  ( T ) = t ] \sum_{t\mid k}\sum_{T\subset S,\operatorname{len}(T)=k/t}[\gcd(T)=t]
 t ∣ k ∑  T ⊂ S , len ( T ) = k / t ∑  [ g cd( T ) = t ] 
对于每一个 t t t  ,找到所有 x ∈ S x\in S x ∈ S   使得 t ∣ x t\mid x t ∣ x  ,这一步可以通过枚举倍数的方式做到 O ( n log  n ) O(n\log n) O ( n log  n )  ,接下来假设 S ′ S' S ′   为满足上述条件的 x x x   且 x ← x t x\gets \frac{x}{t} x ← t x   ,那么:
∑ t ∣ k ∑ T ⊂ S ′ , ∣ T ∣ = k / t [ gcd  ( T ) = 1 ] = ∑ t ∣ k ∑ T ⊂ S , ∣ T ∣ = k / t ∑ d ∣ gcd  ( T ) μ ( d ) = ∑ t ∣ k ∑ d = 1 max  ( S ′ ) μ ( d ) ( ∑ i = 1 n ′ [ d ∣ a i ′ ] k / t ) = ∑ t ∣ k ∑ d = 1 ⌊ max  ( S ) / t ⌋ μ ( d ) ( ∑ i = 1 n [ d t ∣ a i ] k / t ) \begin{aligned}
\sum_{t\mid k}\sum_{T\subset S',|T|=k/t}[\gcd(T)=1]&=\sum_{t\mid k}\sum_{T\subset S,|T|=k/t}\sum_{d\mid \gcd(T)}\mu(d)\\
&=\sum_{t\mid k}\sum_{d=1}^{\max(S')}\mu(d)\binom{\sum_{i=1}^{n'}[d\mid a'_i]}{k/t}\\
&=\sum_{t\mid k}\sum_{d=1}^{\lfloor \max(S)/t\rfloor}\mu(d)\binom{\sum_{i=1}^n[dt\mid a_i]}{k/t}
\end{aligned}
 t ∣ k ∑  T ⊂ S ′ , ∣ T ∣ = k / t ∑  [ g cd( T ) = 1 ]  = t ∣ k ∑  T ⊂ S , ∣ T ∣ = k / t ∑  d ∣ g c d ( T ) ∑  μ ( d ) = t ∣ k ∑  d = 1 ∑ m a x ( S ′ )  μ ( d ) ( k / t ∑ i = 1 n ′  [ d ∣ a i ′  ]  ) = t ∣ k ∑  d = 1 ∑ ⌊ m a x ( S ) / t ⌋  μ ( d ) ( k / t ∑ i = 1 n  [ d t ∣ a i  ]  )  
设 f ( x ) = ∑ i = 1 n [ x ∣ a i ] f(x)=\sum_{i=1}^n [x\mid a_i] f ( x ) = ∑ i = 1 n  [ x ∣ a i  ]  ,这是可以 O ( n log  n ) O(n\log n) O ( n log  n )   预处理的;对于最终要计算的式子,这最坏是 O ( ∑ t = 1 n n t ) = O ( n log  n ) O(\sum_{t=1}^n \frac{n}{t})=O(n\log n) O ( ∑ t = 1 n  t n  ) = O ( n log  n )   的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 #include  <bits/stdc++.h>  using  namespace  std;#define  int long long const  int  N = 600010 , P = 1e9 +7 ;int  n, mx, k, cnt[N], primes[N], mu[N], fact[N], infact[N], f[N], cntp;bitset<N> st; int  qmi (int  a, int  k)   {    int  res = 1 ;     while  (k) {         if  (k & 1 ) res = 1ll  * res * a % P;         a = 1ll  * a * a % P;         k >>= 1 ;     }     return  res; } void  init (int  n)   {    mu[1 ] = 1 ;     for  (int  i = 2 ; i <= n; i++) {         if  (!st[i]) primes[cntp++] = i, mu[i] = -1 ;         for  (int  j = 0 ; primes[j] <= n / i; j++) {             st[i * primes[j]] = 1 ;             if  (i % primes[j]) mu[i * primes[j]] = -mu[i];             else  {                 mu[i * primes[j]] = 0 ;                 break ;             }         }     } } int  C (int  n, int  m)   {    if  (n < m) return  0 ;     return  1ll  * fact[n] * infact[m] % P * infact[n-m] % P; } signed  main ()   {    cin >> n >> k;     fact[0 ] = infact[0 ] = 1 ;     for  (int  i = 1 ; i <= n; i++) fact[i] = 1ll  * fact[i-1 ] * i % P;     infact[n] = qmi (fact[n], P-2 );     for  (int  i = n-1 ; i; i--) infact[i] = 1ll  * (i+1 ) * infact[i+1 ] % P;     for  (int  i = 1 , a; i <= n; i++) cin >> a, cnt[a]++, mx = max (mx, a);     init (mx);     for  (int  i = 1 ; i <= mx; i++)         for  (int  j = i; j <= mx; j += i)             f[i] += cnt[j];          int  res = 0 ;     for  (int  t = 1 ; t <= k; t++) {         if  (k % t) continue ;         for  (int  d = 1 ; d <= mx / t; d++) {             res = (res + 1ll  * mu[d] * C (f[d * t], k / t)) % P;         }     }     if  (res < 0 ) res += P;     cout << res << endl;     return  0 ; }