Luogu1445 [Violet]樱花 ---- 数论优化

Luogu1445 [Violet]樱花

一句话题意:(原本就是一句话的)

求方程 $\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 }
相关文章
相关标签/搜索