1. 程式人生 > >SPOJ DIVCNT2 - Counting Divisors (square)

SPOJ DIVCNT2 - Counting Divisors (square)

題目描述:

i = 1 n σ

0 ( i 2 ) \sum_{i=1}^n\sigma_0(i^2)
其中 σ
0 \sigma_0
表示約數個數, n 1 0 12
n\le10^{12}
,時間限制20s

題目分析:

σ 0 ( i ) = d i σ 0 ( i 2 ) = d i 2 ω ( d ) \large\sigma_0(i)=\sum_{d|i}\\\sigma_0(i^2)=\sum_{d|i}2^{\omega(d)}
其中, ω ( d ) \omega(d) 表示 d d 的質因子個數,上式可以理解為從i中選出一些質因子,每個質因子可以取當前次冪或者加上最高次冪兩種選擇。

可看出 2 ω ( d ) 2^{\omega(d)} 為d的無平方因子個數,所以
2 ω ( d ) = k d μ ( k ) \large2^{\omega(d)}=\sum_{k|d}|\mu(k)|
整理一下,記 g ( i ) = μ ( k ) g(i)=|\mu(k)| ,那麼 σ 0 ( i 2 ) = ( g I ) I = g ( I I ) = g σ 0 \sigma_0(i^2)=(g*I)*I=g*(I*I)=g*\sigma_0
所以 i = 1 n σ 0 ( i 2 ) = i = 1 n d i μ ( i d ) σ 0 ( d ) = i = 1 n μ ( i ) d = 1 n i σ 0 ( d ) \sum_{i=1}^n\sigma_0(i^2)=\sum_{i=1}^n\sum_{d|i}|\mu(\frac id)|*\sigma_0(d) \\=\sum_{i=1}^n|\mu(i)|\sum_{d=1}^{\frac ni}\sigma_0(d)
顯然需要處理 μ ( i ) |\mu(i)| σ 0 ( i ) \sigma_0(i) 的字首和
線性篩五千萬到一億(少了會TLE),剩下的可以這麼算:

  • 從" n n 以內無平方因子數的個數"的意義出發,考慮容斥,可以得出:
    i = 1 n μ ( i ) = i = 1 n μ ( i ) n i 2 \sum_{i=1}^n|\mu(i)|=\sum_{i=1}^{\sqrt n}\mu(i)*\left\lfloor\frac n{i^2}\right\rfloor
    O ( n ) O(\sqrt n) 計算
  • 約數個數的字首和很好算:
    i = 1 n σ 0 ( i ) = i = 1 n n i \sum_{i=1}^n\sigma_0(i)=\sum_{i=1}^n\left\lfloor\frac ni\right\rfloor
    O ( n ) O(\sqrt n) 分塊計算

與杜教篩的時間複雜度分析類似,總時間 O ( n 2 3 ) \large O(n^{\frac 23})

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int N = 50000000;
int p[N/10],mu[N+5],sd[N+5],sm[N+5];
bool v[N+5];
void Prime(int N)
{
	mu[1]