素数判断及筛法

单个素数判断
//素数判断(小数据)
int prime(int n) {
    if (n == 0 || n == 1)  return 0;
    if (n == 2)  return 1;
    if (n % 2 == 0) return 0;
    for (int i = 3; i * i <= n; i = i + 2)
        if (n % i == 0)  return 0;
    return 1;
}


//Miller-Rabin(大素数判定) 单个数字n复杂度15*log(n)
int Mr[30] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
//此数组为测试用的a,这12个可测所有的long long int;
LLI Miller_Rabin(LLI n) {
    if(n == 2)               return true;
    else if(n < 2)          return false;
    if(n % 2 == 0)          return false;
    LLI u = n - 1;
    while(u % 2 == 0)   u = u / 2;
    LLI  tempu = u;
    for(int i = 0; i < 12; i ++) {
        if(Mr[i] >= n)  break;
        u = tempu;
        LLI x = Fast_power(Mr[i],u,n);//这里调用快速幂函数,p18
        while(u < n) {
            LLI y = (x % n) * (x % n) % n;
            //注意!!!(x % n) * (x % n)很可能溢出,如果出现这种情况,用快速乘
            //另外调用快速幂时也可能溢出
            if(y == 1 && x != 1 && x != n - 1)  return false;
            x = y;
            u = u * 2;
        }
        if(x != 1)  return false;
    }
    return true;
}
区间素数筛

//厄拉多塞素数筛法,复杂度>O(n*log(log(n)))
bool mark[maxn];
void sieve_prime() {
    memset(mark, true, sizeof(mark));
    mark[0] = mark[1] = false;
    for (int i = 2; i * i <= maxn; i ++)
        if (mark[i])
            for (int j = i * i; j < maxn; j = j + i)
                mark[j] = false;
}
//欧拉素数筛法复杂度O(n)
bool isPrime[maxn];
LLI primeList[maxn],primeCount = 0;
void Eular_Sieve(LLI n) {
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0] = false;
    isPrime[1] = false;
    for(int i = 2; i <= n; i ++) {
        if(isPrime[i]) {
            primeCount ++;
            primeList[primeCount] = i;
        }
        for(int j = 1; j <= primeCount; j ++) {
            if(i * primeList[j] > n)    break;
            isPrime[i * primeList[j]] = false;
            if(!(i % primeList[j]))    break;
        }
    }
}


素数筛法的应用
题目链接: Help Hanzo

题意就是求[a,b]区间内的素数个数( 1 ≤ a ≤ b < 231, b - a ≤ 100000);
很明显,如果直接筛肯定不行……,见代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define pi acos(-1.0)
#define maxn (500000 + 5)
#define mol 1000000000 + 7
#define Lowbit(x) (x & (-x))
using namespace std;
typedef long long int LLI;

bool flag[100000 + 20];
bool isPrime[maxn];
LLI primeList[maxn],primeCount = 0;
void Eular_Sieve(LLI n) {
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0] = false;
    isPrime[1] = false;
    for(int i = 2; i <= n; i ++) {
        if(isPrime[i]) {
            primeCount ++;
            primeList[primeCount] = i;
        }
        for(int j = 1; j <= primeCount; j ++) {
            if(i * primeList[j] > n)    break;
            isPrime[i * primeList[j]] = false;
            if(!(i % primeList[j]))    break;
        }
    }
}

int main() {
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    Eular_Sieve(maxn);
    int t;
    scanf("%d",&t);
    for(int Case = 1; Case <= t; Case ++) {
        int l,r,n,cnt = 0;
        memset(flag,true,sizeof(flag));
        scanf("%d%d",&l,&r);
        if(l == 1)  l ++;
        n = r - l;
        for(int i = 1; i <= primeCount && primeList[i] * primeList[i] <= r; i ++) {
            int j = 0;
            if(l % primeList[i] != 0)   j = primeList[i] - l % primeList[i];
            if(l <= primeList[i])       j += primeList[i];
            for(; j <= n; j += primeList[i])    flag[j] = false;
        }
        for(int i = 0;i <= n;i ++)
            if(flag[i]) cnt ++;
        printf("Case %d: %d\n",Case,cnt);
    }
    return 0;
}



你可能感兴趣的:(数学)