素数表模板
一.筛选法
假设要求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;
}