数论--素数

Posted 东流vip

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论--素数相关的知识,希望对你有一定的参考价值。

1.素数筛(线筛):

时间复杂度为O(n),可以筛选出n以内的所有素数,共有tot个,prime[x]==true,则x是素数

筛选原理:

任意一个数乘以比它小的素数的结果都是合数

遇到最小质因子就跳出循环,保证每个合数被其最小质因子筛去

附上代码:

 1 #include<cstdio>
 2 const int N = 100000 + 5;
 3 bool prime[N];//prime[i]表示i是不是质数
 4 int p[N], tot=0;//p[N]用来存质数,tot为素数的个数
 5 void init(int n){
 6     prime[1]=false;
 7     for(int i = 2; i <=n; i ++) prime[i] = true;//初始化为质数
 8     for(int i = 2; i <=n; i++){
 9         if(prime[i]) p[tot ++] = i;//把质数存起来
10         for(int j = 0; j < tot && i * p[j] <=n; j++){
11             prime[i * p[j]] = false;
12             if(i % p[j] == 0) break;//保证每个合数被它最小的质因数筛去
13         }
14     }
15 }
16 int main(){
17     init(11);
18     for(int i=0;i<tot;i++)
19     printf("%d\\n",p[i]);
20     printf("tot=%d\\n",tot);
21 }

利用了每个合数必有一个最小素因子。每个合数仅被它的最小素因子筛去正好一次。所以为线性时间。

 

2.埃筛--------------埃拉托斯特尼筛法,或者叫埃氏筛法

原理:

任意一个素数的倍数都是合数

过程图解:

代码也很好写:

 1 #include<cstdio>
 2 const int N = 100000 + 5;
 3 bool prime[N];
 4 void init(){
 5     for(int i = 2; i <= N; i ++) prime[i] = true;
 6     for(int i = 2; i*i <= N; i ++){//判断改成i*i<N 
 7         if(prime[i]){
 8             for(int j = i*i; j <= N; j += i){//从i*i开始就可以了 
 9                 prime[j] = false;  
10             }
11         }
12     }
13 }
14 int main(){
15     init();
16 }

时间复杂度为O(n*loglog n),因为loglog n非常小,基本上和线筛无区别,较常用

 

(还有个规律,除了2,3,其他的素数一定在6的倍数的旁边,ji

基于埃筛的原理,我们可以用它干很多事

 

3.预处理每个数的所有质因数:

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int N = 100000 + 5;
 5 vector<int > prime_factor[N];
 6 void init(){
 7     for(int i = 2; i <= N; i ++){
 8         if(prime_factor[i].size() == 0){//如果i是质数
 9             for(int j = i; j <= N; j += i){
10                 prime_factor[j].push_back(i);
11             }
12         }
13     }
14 }
15 int main(){
16     init();
17     for(int i=0;i<prime_factor[60].size();i++)
18     printf("%d ",prime_factor[60][i]);//60的所有素因子
19 }

如果把判断i是质数的判断(第8行),则是预处理每个数的因数

 

4.预处理每个数的质因数分解

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int N = 100000 + 5;
 5 vector<int > prime_factor[N];
 6 void init(){
 7     int temp;
 8     for(int i = 2; i < N; i ++){
 9         if(prime_factor[i].size() == 0){
10             for(int j = i; j < N; j += i){
11                 temp = j;
12                 while(temp % i == 0){
13                     prime_factor[j].push_back(i);
14                     temp /= i;
15                 }
16             }
17         }
18     }
19 }
20 int main(){
21     init();
22     for(int i=0;i<prime_factor[60].size();i++)
23     printf("%d ",prime_factor[60][i]);
24 }

 

以上是关于数论--素数的主要内容,如果未能解决你的问题,请参考以下文章

数论--素数

三 数论的编程实验

数论——HDU - 2136

数论1.素数判断

数论_筛法求素数

算法15---数论6---素数,回文素数 分解质因素