继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

素数

holdtom
关注TA
已关注
手记 1842
粉丝 240
获赞 991


埃氏筛法

#define  exp 2.7182818285

#define  Y 0.57721566490153286060651209

#define  ln2 0.69314718055995

#define  ln3 1.0986122886681

#define  lg2 0.301029995663981

#define  lg5 0.698970004336018

#define  ln5 1.6094379124341

int prime[N];

void pre()

{

    memset(prime,1,sizeof(prime));prime[1]=0;

    for(int i=2;i<N;i++)

    {

        if(prime[i])

        for(int j=2*i;j<N;j+=i)prime[j]=0;

    }

}

线性筛

int p[MAX],cnt;

bool isprime[MAX];

void prime()

{

    cnt=1;

    memset(isprime,1,sizeof(isprime));//初始化认为所有数都为素数

    isprime[0]=isprime[1]=0;//0和1不是素数

    for(int i=2;i<MAX;i++)

    {

        if(isprime[i])

        p[cnt++]=i;//保存素数i

        for(int j=1;j<cnt&&p[j]*i<MAX;j++)

        {

            isprime[p[j]*i]=0;

            If(i%isprimep[j]=0)break;

            //筛掉小于等于i的素数和i的积构成的合数

        }

    }

}

Meisell-Lehmer

//求n以内的素数个数

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 5*1e6 + 2;

bool np[N];

int prime[N], pi[N];

int getprime() {

    int cnt = 0;

    np[0] = np[1] = true;

    pi[0] = pi[1] = 0;

    for(int i = 2; i < N; ++i) {

        if(!np[i]) prime[++cnt] = i;

        pi[i] = cnt;

        for(int j = 1; j <= cnt && i * prime[j] < N; ++j) {

            np[i * prime[j]] = true;

            if(i % prime[j] == 0)   break;

        }

    }

    return cnt;

}

const int M = 7;

const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;

int phi[PM + 1][M + 1], sz[M + 1];

void init() {

    getprime();

    sz[0] = 1;

    for(int i = 0; i <= PM; ++i)  phi[i][0] = i;

    for(int i = 1; i <= M; ++i) {

        sz[i] = prime[i] * sz[i - 1];

        for(int j = 1; j <= PM; ++j) {

            phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];

        }

    }

}

int sqrt2(LL x) {

    LL r = (LL)sqrt(x - 0.1);

    while(r * r <= x)   ++r;

    return int(r - 1);

}

int sqrt3(LL x) {

    LL r = (LL)cbrt(x - 0.1);

    while(r * r * r <= x)   ++r;

    return int(r - 1);

}

LL getphi(LL x, int s) {

    if(s == 0)  return x;

    if(s <= M)  return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];

    if(x <= prime[s]*prime[s])   return pi[x] - s + 1;

    if(x <= prime[s]*prime[s]*prime[s] && x < N) {

        int s2x = pi[sqrt2(x)];

        LL ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;

        for(int i = s + 1; i <= s2x; ++i) {

            ans += pi[x / prime[i]];

        }

        return ans;

    }

    return getphi(x, s - 1) - getphi(x / prime[s], s - 1);

}

LL getpi(LL x) {

    if(x < N)   return pi[x];

    LL ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;

    for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i) {

        ans -= getpi(x / prime[i]) - i + 1;

    }

    return ans;

}

LL lehmer_pi(LL x) {

    if(x < N)   return pi[x];

    int a = (int)lehmer_pi(sqrt2(sqrt2(x)));

    int b = (int)lehmer_pi(sqrt2(x));

    int c = (int)lehmer_pi(sqrt3(x));

    LL sum = getphi(x, a) + LL(b + a - 2) * (b - a + 1) / 2;

    for (int i = a + 1; i <= b; i++) {

        LL w = x / prime[i];

        sum -= lehmer_pi(w);

        if (i > c) continue;

        LL lim = lehmer_pi(sqrt2(w));

        for (int j = i; j <= lim; j++) {

            sum -= lehmer_pi(w / prime[j]) - (j - 1);

        }

    }

    return sum;

}

int main() {

    init();

    LL n;

    while(cin >> n) {

        cout << lehmer_pi(n) << endl;

    }

}

Min_25  prime<n

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#define M 5333333

using namespace std;

typedef long long ll;

ll A[M], B[M];

double inv[M];

int main() {

    ll n;

    scanf("%lld", &n);

    int lim = sqrt(n) + 1;

    if(n <= 10) return printf("%d\n", (n >= 2) + (n >= 3) + (n >= 5) + (n >= 7)), 0;

    for(int i = 1; i <= lim; i++) inv[i] = 1.0/ (i * 2 - 1), A[i] = (n / (i * 2 - 1) + 1) / 2, B[i] = (i + 1) / 2 - (i == 1);

    for(int i = 3; i <= lim; i += 2)if(B[i] != B[i - 1]) {

        unsigned l = B[i - 1];

        for(int j = 1; i * (j * 2 - 1) <= lim; j++) A[j] -= A[i * j - (i - 1) / 2] - l;

        double tmp = n / i;

        for(int j = (lim / i + 1) / 2 + 1, s = min(n / i / i, (ll) lim); j * 2 - 1 <= s; j++) A[j] -= B[(int) (tmp * inv[j] + 1e-7)] - l;

        for(int j = lim / i; j >= i; j--)

        for(int k = i - 1; k >= 0; k--) B[j * i + k] -= B[j] - l;

    }

    printf("%lld\n", A[1]);

    return 0;

}

Miller-rabin

//判断n是否为素数

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cmath>

#include <cstring>

#include <map>

using namespace std;

 

const int times = 20;

int number = 0;

 

//map<long long, int>m;

long long Random( long long n )         //生成[ 0 , n ]的随机数

{

    return ((double)rand( ) / RAND_MAX*n + 0.5);

}

 

long long q_mul( long long a, long long b, long long mod ) //快速计算 (a*b) % mod

{

    long long ans = 0;

    while(b)

    {

        if(b & 1)

        {

            b--;

            ans =(ans+ a)%mod;

        }

        b /= 2;

        a = (a + a) % mod;

 

    }

    return ans;

}

 

long long q_pow( long long a, long long b, long long mod ) //快速计算 (a^b) % mod

{

    long long ans = 1;

    while(b)

    {

        if(b & 1)

        {

            ans = q_mul( ans, a, mod );

        }

        b /= 2;

        a = q_mul( a, a, mod );

    }

    return ans;

}

 

bool witness( long long a, long long n )//miller_rabin算法的精华

{//用检验算子a来检验n是不是素数

    long long tem = n - 1;

    int j = 0;

    while(tem % 2 == 0)

    {

        tem /= 2;

        j++;

    }

    //将n-1拆分为a^r * s

 

    long long x = q_pow( a, tem, n ); //得到a^r mod n

    if(x == 1 || x == n - 1) return true;   //余数为1则为素数

    while(j--) //否则试验条件2看是否有满足的 j

    {

        x = q_mul( x, x, n );

        if(x == n - 1) return true;

    }

    return false;

}

 

bool miller_rabin( long long n )  //检验n是否是素数

{

 

    if(n == 2)

        return true;

    if(n < 2 || n % 2 == 0)

        return false;               //如果是2则是素数,如果<2或者是>2的偶数则不是素数

 

    for(int i = 1; i <= times; i++)  //做times次随机检验

    {

        long long a = Random( n - 2 ) + 1; //得到随机检验算子 a

        if(!witness( a, n ))                        //用a检验n是否是素数

            return false;

    }

    return true;

}

 main( )

{

   int t;cin>>t;

   while(t--)

   {

       long long n;scanf("%lld",&n);

       if(miller_rabin(n))

       {

           puts("Prime");continue;

       }

        else puts("NO");

   }

}

©著作权归作者所有:来自51CTO博客作者qinXpeng的原创作品,如需转载,请注明出处,否则将追究法律责任


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP