素数相关问题

判断一个数是不是素数:

bool prime(int n)
{
    if(n==0||n==1) return false;
    if(n==2) return true;
    for(int i=2;i<=sqrt(n);i++)
        if(n%i==0)
            return false;
    return true;
}

区间筛素数(区间内素数的个数):

#include <stdio.h>
#include <cmath>
#include <cstring>
const int maxn = 1000001;


int PrimeList[maxn];
int PrimeNum;
bool IsNotPrime[maxn]; // IsNotPrime[i] = 1表示i + L这个数是素数.


void SegmentPrime(int L, int U)
{
    // 求区间[L, 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;
    PrimeNum = 0;
    for (i = 0; i < d; i++) if (!IsNotPrime[i]) PrimeList[PrimeNum++] = i + L;
}
int main()
{
    int l,r;
    while(scanf("%d%d",&l,&r)==2)
    {
        SegmentPrime(l,r);
        printf("%d
",PrimeNum);
    }
    return 0;
}

区间筛素数(区间内相邻的差最小和最大的素数)

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1e6;
int prime[maxn+10];

void getPrime()
{
    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;
        }
    }
}
bool isprime[maxn+10];
int prime2[maxn+10];
void getPrime2(int L,int R)
{
    memset(isprime,1,sizeof(isprime));
    if(L<2) L=2;
    for(int i=1;i<=prime[0]&&(long long)prime[i]*prime[i]<=R;i++)
    {
        int s=L/prime[i]+(L%prime[i]>0);
        if(s==1)
            s=2;
        for(int j=s;(long long)j*prime[i]<=R;j++)
            if((long long)j*prime[i]>=L)
            isprime[j*prime[i]-L]=false; 
    }
    prime2[0]=0;
    for(int i=0;i<=R-L;i++)
        if(isprime[i])
        prime2[++prime2[0]]=i+L;
}
int main()
{
    getPrime();
    int L,R;
    while(scanf("%d%d",&L,&R)!=EOF)
    {
        getPrime2(L,R);
        if(prime2[0]<2)
            printf("There are no adjacent primes.
");
        else
        {
            int x1=0,x2=1000000,y1=0,y2=0;
            for(int i=1;i<prime2[0];i++)
            {
                if(prime2[i+1]-prime2[i]<x2-x1)
                {
                    x1=prime2[i];
                    x2=prime2[i+1];
                }
                if(prime2[i+1]-prime2[i]>y2-y1)
                {
                    y1=prime2[i];
                    y2=prime2[i+1];
                }
            }
            printf("%d,%d are closest, %d,%d are most distant.
",x1,x2,y1,y2);
        }
    }
    return 0;
}

 素数测试,若不是素数,输出它的最小素因子:

//写得太好了,每一个函数都是一个模版呀~~~~
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define gcc 10007
#define MAX ((INT)1<<63)-1

using namespace std;

typedef unsigned long long INT;
INT p[10]={2,3,5,7,11,13,17,19,23,29};
inline INT gcd(INT a,INT b)
{
    INT m=1;
    if(!b)    return a;
    while(m)
    {
        m=a%b;
        a=b;
        b=m;
    }
    return a;
}

//计算a*b%n

inline INT multi_mod(INT a,INT b,INT mod)
{
    INT sum=0;
    while(b)
    {
        if(b&1)    sum=(sum+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return sum;
}

//计算a^b%n;

inline INT quickmod(INT a,INT b,INT mod)
{
    INT sum=1;
    while(b)
    {
        if(b&1)    sum=multi_mod(sum,a,mod);
        a=multi_mod(a,a,mod);
        b>>=1;
    }
    return sum;
}

bool miller_rabin(INT n)
{
    int i,j,k=0;
    INT u,m,buf;
    //将n分解为m*2^k
    if(n==2)
        return true;
    if(n<2||!(n&1))
        return false;
    m=n-1;
    while(!(m&1))
        k++,m>>=1;
    for(i=0;i<9;i++)
    {
        if(p[i]>=n)
            return true;
        u=quickmod(p[i],m,n);
        if(u==1)
            continue;
        for(j=0;j<k;j++)
        {
            buf=multi_mod(u,u,n);
            if(buf==1&&u!=1&&u!=n-1)
                return false;
            u=buf;
        }
        //如果p[i]^(n-1)%n!=1那么n为合数
        if(u-1)
            return false;
    }
    return true;
}

//寻找n的一个因子,该因子并不一定是最小的,所以下面要二分查找最小的那个因子
INT pollard(INT n)
{
    INT i=1;
    INT x=rand()%(n-1)+1;
    INT y=x;
    INT k=2;
    INT d;
    do
    {
        i++;
        d=gcd(n+y-x,n);
        if(d>1&&d<n)
            return d;
        if(i==k)
            y=x,k*=2;
        x=(multi_mod(x,x,n)+n-gcc)%n;
    }while(y!=x);
    return n;
}

INT MIN;

INT pollard_min(INT n)
{
    INT p,a,b=MAX;
    if(n==1)    return MAX;
    if(miller_rabin(n))    return n;
    p=pollard(n);
    a=pollard_min(p);//二分查找
    INT y=n/p;
    b=pollard_min(y);
    return a<b?a:b;
}

int main(void)
{
    INT T;
    INT n;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        MIN=MAX;
        if(miller_rabin(n))
        {
            puts("Prime");
        }
        else printf("%lld
",pollard_min(n));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/scottding/p/4333998.html