素数表生成模板 与 合数进行素因子分解模板

素数表模板

一.筛选法

假设要求1~100的素数
2
是素数, 删除2*2, 2*3, 2*4,…, 2*50
第一个没被删除的是3,删除3*3, 3*4,3*5,…,3*33
第一个没被删除的是5,删除5*5, 5*6, … 5*20
得到素数p,需要删除p*p, p*(p+1), …p*[n/p],运算量为[n/p]-p,其中p不超过n1/2

#include<cstring>
#include<cmath>
const int MAX =10005 ;
bool isprime[MAX] ;
int prime_table[MAX] ;
int prime_num ;
 
//检查前MAX个数字是否为素数
void search_prime()
{
     memset(isprime,1,sizeof(isprime)) ;
     isprime[1] = 0 ;
     for(int i = 2 ; i <=sqrt(MAX+0.5) ;i ++)
     {
             if(isprime[i] == 1)
             {
                         int j = i * 2 ;
                         while(j <= MAX)
                         {
                                 isprime[j] = 0;
                                 j += i ;
                         }
             }
     }
} 
//生成一个素数表
void prime_Table()
{
     prime_num = 0 ;
     for(int i = 1 ; i <= MAX ; i ++)
     {
             if(isprime[i] == 1 )
             {
                         prime_table[prime_num++ ] = i ;
             }
     }
}


 二.复杂度O(n)

prime[0]记录有多少素数prime_num

假设要求1~100的素数
2
是素数,prime[0]1,把prime[1] = 2; 搜索 2*prime[1] = 4,得出4不是素数, break

3是素数,prime[0]2,把prime[2] = 3 ; 搜素 3*2 ,得出6不是素数 ; 3 * 3,得出9不是素数 ,break

4不是素数 , prime[0]仍为2,搜索 4 * 2 = 8 4 * 3 = 12,都得出不是素数

5是素数,prime[0]3,把prime[3] = 5;  搜索 5 * 2 5 * 3 5 * 5,都不是素数 ,break

总之,对一个数a,那么 a乘以 小于或等于a的素数 的乘积都是合数,从而消去后面的合数。

这个方法求得的效率比上面的方法高。

断言:如果一个数x是合数,那么它一定能表示成一个素数i与一个数j的乘积,其中j>=i且j的最小素因子大于等于i。

#include<cstring>
const int MAXP = 1000000;  
int prime[MAXP];  
bool is_prime[MAXP];  
void prime_list()  
{  
   memset(is_prime,true,sizeof(is_prime));  
    for (int i = 2;i <= MAXP;i++)  
    {  
        if (is_prime[i])  
            prime[++prime[0]] = i;  
        for (int j = 1,k; (j <= prime[0])&& (k = i * prime[j]) <= MAXP;j++)
        //i依次与符合要求的素数prime[j]相乘构成所有合数。   
        {  
            is_prime[k] = false;  
            if(i % prime[j] == 0) break;
            //当前循环到i(i可能为素数或合数),小于i的所有素数已经保存到prime[1]到prime[prime[0]]中了,所以如果有i的最小素因子一定第一时间退出
        }  
    }  
}


 

 优化版

 

#include<cstring>
const int MAXN=20000;
int prime[MAXN+1];
int getPrime()//得到小于等于MAXN的素数,prime[0]存放的是个数
{
   memset(prime,0,sizeof(prime));
    for(int i=2;i<=MAXN;i++)
    {
        if ( !prime[i])  prime[++prime[0]]=i;
        for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++)
        {
           prime[prime[j]*i]=1;
           if(i%prime[j]==0) break;
        }
    }
    return prime[0];
}

合数进行素因子分解模板

factor[i][0]中放的是x的第i+1个素因子,factor[i][1]中放的是该因子的次数(幂)。

facCnt是x素因子的总个数。

long long factor[100][2];
int facCnt;
int getFactors(long long x)
{//把x进行素数分解,factor[0][0]是x的第一个素因子,factor[0][1]是该因子在x中的幂
    facCnt=0;
    long long tmp=x;
    for(int i=1;prime[i]<=tmp/prime[i];i++)//temp至少为prime[i]的平方才计算。
    {
        factor[facCnt][1]=0;
        if(tmp%prime[i]==0)
        {
            factor[facCnt][0]=prime[i];
            while(tmp%prime[i]==0)
            {
                   factor[facCnt][1]++;
                   tmp/=prime[i];
            }
            facCnt++;
        }
    }
    if(tmp!=1)//此时的tmp为最大的素数
    {
        factor[facCnt][0]=tmp;
        factor[facCnt++][1]=1;
    }
    return facCnt;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值