求方程 $\frac{1}{X} + \frac{1}{Y} = \frac{1}{N!}$ 的正整數解的組數,其中$N \leq 10^6$算法
差很少是第一篇公開的題解,由於之前的太爛了,不敢發......spa
咱們觀察到提交記錄發現彷佛時間有從200ms+到8ms-的,然而標準題解中給出的代碼就是跑的比較慢的......code
因此有沒有什麼快一點的呢?blog
假設此時你已經用樸素算法A過此題遞歸
因而咱們分析算法:it
樓下題解的複雜度是$O(nlogn+常數的)$,平均200msio
有沒有什麼更快的呢?class
假設咱們分析到了原理
$A*B=(n!)*(n!)$im
的時候發現最終求的就是約數個數
首先若是求m的約數個數的話,那麼對m分解獲得
$m=p_1^{k_1}*p_2^{k_2}...$
其中$p_1,p_2,p_3...$都是質數
那麼根據乘法原理
$Ans = (k_1 + 1) * (k_2 + 1)...$
而後對於階乘來講,對n!作質因數分解實則在分解1 * 2 * ... * n
然而這個就是樸素的作法,然而因爲你實則是須要求質因數的指數,而在《初等數論》中有
$\Sigma(p \leq n, p \ is \ a \ prime)\Sigma_{k=0}^{p^k \leq n}(\lfloor \frac{n}{p^k} \rfloor)$
因此咱們直接遞歸(或者非遞歸地)跑這個公式便可
實際食用:枚舉質數(或打表)(在階乘下質因數等價於質數)(O(n)),而後對於全部質數,跑公式。
n內大約有n/ln(n)個質數,而後每次作都是log的,因此複雜度爲O(n/ln(n) * log(n))=O(n),常數小,瓶頸在篩質數那......
代碼以下:
1 //Source Code 2 3 const int MAXN = 1000111; 4 const int MODS = 1000000007; 5 6 int n, tot; 7 int prime[MAXN]; 8 bool is_not_prime[MAXN]; 9 10 inline void Get_Prime(){ 11 for(int i = 2; i <= n; i++){ 12 if(!is_not_prime[i]) 13 prime[++tot] = i; 14 for(int j = 1; j <= tot; j++){ 15 if(i * prime[j] > n) break; 16 is_not_prime[i * prime[j]] = true; 17 if(!(i % prime[j])) break; 18 } 19 } 20 } 21 22 inline int Get_D(const int &tar, const int &p){ 23 if(tar < p) return 0; 24 return tar / p + Get_D(tar / p, p); 25 } 26 27 int main(){ 28 Main_Init(); 29 n = read(); 30 Get_Prime(); 31 long long ans = 1; 32 for(int i = 1; i <= tot; i++) 33 (ans *= (Get_D(n, prime[i]) << 1) + 1) %= MODS; 34 write('\n', ans); 35 Main_Init(); 36 return 0; 37 }