素数筛选 及 最小公倍数

辗转相除法求最大公约数 及 素数筛选

GCD与LCM

求a,b的最大公约数--gcd

求a,b的最小公倍数--lcm

inline unsigned int gcd(unsigned int a, unsigned int b){  
    while( b ^= a ^= b ^= a %= b ); return a;  
}  
inline unsigned int lcm(unsigned int a,unsigned int b){  
    return a / gcd( a, b ) * b;  
}

2进制版本GCD

int gcd(int x, int y)   
{
        int i, j;
        if( x == 0 ) return y;
        if( y == 0 ) return x;
        for(i = 0; 0 == (x & 1) ; ++i) x >>= 1;
        for(j = 0; 0 == ( y & 1) ;++j) y >>= 1;
        if( j < i ) i = j;
        while( true )
		{
                if( x < y ) x ^= y, y ^= x, x ^= y;   
                if(0 == ( x -= y ) ) return y << i; 
                while(0 == ( x & 1 )) x >>= 1;
        }
}


线性素数筛选

线性筛选,如果num为素数,则isNotPrime[num] = 0,primeList为素数集合,PrimeCtr为集合大小

素数下标从1开始到PrimeCtr

const int maxn = 100;  
int isNotPrime[maxn+5];
int primeList[maxn], PrimeCtr;  

void getPrime()  
{  
    PrimeCtr = 0;  isNotPrime[0] = isNotPrime[1] = 1;  
    for(int i = 2; i <= maxn; ++i)  
    {  
        if( !isNotPrime[i] ) primeList[ ++PrimeCtr ] = i;  
        for(int j = 1; j <= PrimeCtr && i * primeList[j] <= maxn; j++)  
        {  
            isNotPrime[i * primeList[j]] = true;  
            if( i % primeList[j] == 0 ) break;  
        }  
    }  
} 


区间筛选

下标从0开始到PrimeCtr-1

#include<iostream>  
#include<algorithm>  
#include<cmath>  
using namespace std;   
const int maxn = 100000;  
  
int  PrimeList[maxn], PrimeCtr;   
bool IsNotPrime[maxn]; /* IsNotPrime[i] = 1表示i + L这个数不是素数. */ 

void SegmentPrime(int L, int U)  
{  
     int i,j;  
     int SU = sqrt( 1.0 * U );  
     int d = U - L + 1;  
     for(i = 0; i < d; ++i) IsNotPrime[i] = 0; /*一开始全是素数*/  
     for(i=(L % 2 != 0); i < d; i += 2)  
          IsNotPrime[i] = 1; /*把偶数的直接去掉*/  
     for (i = 3; i <= SU; i += 2)  
     {  
           if (i > L && IsNotPrime[i - L]) continue;   
           /* IsNotPrime[i - L] == 1说明i不是素数. */ 
           j = (L / i) * i; /* j为i的倍数,且最接近L的数. */ 
           if (j < L) j += i;  
           if (j == i) j += i; /*i为素数,j = i说明j也是素数,所以直接 + i*/  
           j=j-L;  
           for(; j < d; j += i) IsNotPrime[j] = 1;   
           /* 说明j不是素数(IsNotPrime[j - L] = 1). */  
     }  
     if (L <= 1) IsNotPrime[1 - L] = 1;  
     if (L <= 2) IsNotPrime[2 - L] = 0;  
     PrimeCtr = 0;  
     for (i = 0; i < d; i++)   
          if (!IsNotPrime[i])   
                 PrimeList[PrimeCtr++] = i + L;  
}  
  
  
int main()  
{  
    SegmentPrime(5,100);  
    for(int i = 0; i < PrimeCtr;++i)  /* 注意素数id是从0到PrimeCtr-1 */  
    printf("%d\n",PrimeList[i]);  
} 

朴素筛选素数

const int maxn = 0xfff;
void getPrime()
{
	bool isPrime[maxn];  
  
	memset(isPrime, true, sizeof(isPrime));  
	isPrime[0] = isPrime[1] = false;  
	  
	for(int i = 2; i < max; i++)  
	{  
	    if(isPrime[i])  
	    {  
	        for(int j = 2 * i; j < max; j += i)  
	            isPrime[j] = false;  
	    }  
	}
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值