普通素数 筛法求素数 二次筛法求素数 MillerRabin素数测试【模板】

来源:互联网 发布:时光八音盒 java版 编辑:程序博客网 时间:2024/06/06 11:50

素数和合数共同的性质:

1.a > 1是合数,当且仅当a = b * c,其中1 < b < a,1 < c < a。

2.合数必有素数因子。

3.如果d > 1,p是素数,且d | q,则d = p。

4.设p是素数且p | a*b,则必有p | a或者p | b。

素数的性质:

1.存在无穷多个素数。

2.每个大于1的正整数都有一个素因子。

素数的分布:

素数定理:用π(x)估计小于正整数x的素数有多少个。随着x的增长,π(x) / (x/ln x) = 1。

推论:令pn是第n个素数,其中n是正整数,那么pn ~ n*ln n。

素数的猜想:

1.波特兰猜想:对于任意给定的正整数n,其中n > 1,存在一个素数p,使得n < p < 2*n。

2.孪生素数猜想:存在无穷多的形如p和p+2的素数对。

3.哥德巴赫猜想:每个大于2的正偶数可以写成两个素数的和。可推出任一大于7的奇数都可

写成三个质数之和的猜想。

普通素数判断

int IsPrime(int N)      //注意#include<cmath>{    if(N <= 1)  return 0;    int i;    for(i = 2; i <= sqrt(N*1.0); ++i)        if(N%i == 0)            return 0;    return 1;}

筛法求素数[1,N]

const int MAXN = 1000000;bool Prime[MAXN+100];   //Prime[i] == true表示i为素数void IsPrime(){    for(int i = 2; i <= MAXN; ++i)        Prime[i] = true;    for(int i = 2; i <= MAXN; ++i)        if(Prime[i])            for(int j = i+i; j <= MAXN; j+=i)                Prime[j] = false;}

二次筛法求素数[L,R]

bool Prime[50010];      //存50000内素数判断结果int Primer[1000010];    //存放区间[L,R]之间的素数bool Prime1[1000010];   //判断区间[L,R]中的数是否为素数int IsPrime()//第一次筛50000内的素数{    int num = 0;    for(int i = 2; i <= 50000; i++)        Prime[i] = true;    for(int i = 2; i <= 50000; i++)    {        if(Prime[i])        {            Primer[num++] = i;            for(int j = i+i; j <= 50000; j+=i)                Prime[j] = false;        }    }    return num;     //num为50000范围内的素数个数}int IsPrime2(__int64 a,__int64 b)/*在第一次筛素数的基础上,利用50000以内的素数,筛去范围【a,b】之间的素数倍数,剩下则为素数*/{    int num = IsPrime();    memset(Prime1,true,sizeof(Prime1));    //Prime1数组用来存放范围【a,b】的素性判断    if(a == 1)  //这里注意1不是素数        Prime1[0] = 0; //这里表示0+1不为素数    for(__int64 i = 0; i < num && Primer[i] * Primer[i] <= b; i++)    {        __int64 begin = a/Primer[i] + (a%Primer[i] != 0);        //上边的a/Primer算出应a为素数Primer[i]的多少倍        //(a%Primer[i]!=0)表示应从Primer[i]的a/Primer[i]倍开始筛,还是a/Primer[i]+1倍筛        if(begin == 1)//若得出结果为所被筛素数的1倍,则从该素数的2倍开始筛            begin++;        for(begin = begin*Primer[i]; begin <= b; begin += Primer[i])            Prime1[begin - a] = false;    }    //这里重新利用Primer数组,用来存放区间【a,b】间的素数,num为素数个数    memset(Primer,0,sizeof(Primer));    num = 0;    for(__int64 i = a; i <= b; i++)        if(Prime1[i-a]==1)            Primer[num++] = i-a;    return num;     //num为区间[a,b]的素数个数}

Miller素数测试方法

#include<stdio.h>#include<stdlib.h>#include<time.h>#include<math.h>#define MAX_VAL (pow(2.0,60))#define LL __int64/*LL mod_mul(LL x,LL y,LL mo)   //计算x * y % mo{    LL t;    x %= mo;    for(t = 0; y; x = (x<<1)%mo,y>>=1)        if(y & 1)            t = (t+x) %mo;    return t;}*/LL mod_mul(LL x,LL y,LL mo)     //计算x * y % mo{    LL t,T,a,b,c,d,e,f,g,h,v,ans;    T = (LL)(sqrt(double(mo)+0.5));    t = T*T - mo;    a = x / T;    b = x % T;    c = y / T;    d = y % T;    e = a*c / T;    f = a*c % T;    v = ((a*d+b*c)%mo + e*t) % mo;    g = v / T;    h = v % T;    ans = (((f+g)*t%mo + b*d)% mo + h*T)%mo;    while(ans < 0)        ans += mo;    return ans;}LL mod_exp(LL num,LL t,LL mo)   //计算num^t % mo{    LL ret = 1, temp = num % mo;    for(; t; t >>=1,temp=mod_mul(temp,temp,mo))        if(t & 1)            ret = mod_mul(ret,temp,mo);    return ret;}bool miller_rabbin(LL n)    //miller_rabbin素性测试{    if(n == 2)  return true;    if(n < 2 || !(n&1))     return false;    int t = 0;    LL a,x,y,u = n-1;    while((u & 1) == 0)    {        t++;        u >>= 1;    }    for(int i = 0; i < 50; i++)    {        a = rand() % (n-1)+1;        x = mod_exp(a,u,n);        for(int j = 0; j < t; j++)        {            y = mod_mul(x,x,n);            if(y == 1 && x != 1 && x != n-1)    return false;            x = y;        }        if(x != 1)  return false;    }    return true;}



0 0
原创粉丝点击