Miller——Rabin 素数测试

证明过程

https://blog.csdn.net/djz_zxd/article/details/53456321

代码:

1.误差大,编写简单

int is_not_prime[100000001];
int prime[10000001];
int num_prime;;
void Prime(int n)
{
    for(int i=2; i<=n; ++i)
    {
        if( !is_not_prime[i])
            prime[num_prime++]=i;
        //关键处1
        for(int j=0; j<num_prime&&prime[j]*i<=n; ++j)
        {
            is_not_prime[prime[j]*i]=1;
            if(!(i%prime[j]))//关键处2
                break;
        }
    }
}
int modular_exp(int a,int n,int mod)
{
    int ret=1;
    a%=mod;
    while(n)
    {
        if(n&1)
            ret=a*ret%mod,n--;
        a=a*a%mod;
        n>>=1;
    }
    return ret;;
}
bool miller_rabin1(int n)//误差很大
{
    if(n==0||n==1)
        return false;
    if(n==2)
        return true;
    for(int i=2;i<10;++i)
    {
        int a=rand()%(n-2)+2;
        if(modular_exp(a,n,n)!=a)
            return false;
    }
    return true;
}

2.基本没有误差

ll gcd(ll a,ll b)//求最大公约数
{
    return b?gcd(b,a%b):a;
}
ll multi(ll a,ll b,ll mod)//快速加法求模
{
    ll ret=0;
    while(b)
    {
        if(b&1)
            ret=(ret+a)%mod,b--;
        a=(a+a)%mod;
        b>>=1;
    }
    return ret;
}
ll power(ll a,ll b,ll mod)
{
    ll ret=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            ret=multi(ret,a,mod),b--;
        a=multi(a,a,mod);
        b>>=1;
    }
    return ret;
}
bool miller_rabin2(ll n)
{
    if(n==2)
        return true;
    if(n<2||!(n&1))
        return false;
    ll m=n-1;
    ll cnt=0;
    while(!(m&1))
    {
        ++cnt;
        m>>=1;
    }
    for(int i=0; i<Times; ++i)//Times==10
    {
        ll a=rand()%(n-1)+1;
        ll x=power(a,m,n);
        ll y=0;
        for(int j=0; j<cnt; ++j)
        {
            y=multi(x,x,n);
            if(y==1&&x!=1&&x!=n-1)
                return false;
            x=y;
        }
        if(y!=1)
            return false;
    }
    return true;
}

整体代码:

#include<bits/stdc++.h>
using namespace std;
int is_not_prime[100000001];
int prime[10000001];
int num_prime;;
void Prime(int n)
{
    for(int i=2; i<=n; ++i)
    {
        if( !is_not_prime[i])
            prime[num_prime++]=i;
        //关键处1
        for(int j=0; j<num_prime&&prime[j]*i<=n; ++j)
        {
            is_not_prime[prime[j]*i]=1;
            if(!(i%prime[j]))//关键处2
                break;
        }
    }
}
int modular_exp(int a,int n,int mod)
{
    int ret=1;
    a%=mod;
    while(n)
    {
        if(n&1)
            ret=a*ret%mod,n--;
        a=a*a%mod;
        n>>=1;
    }
    return ret;;
}
bool miller_rabin1(int n)//误差很大
{
    if(n==0||n==1)
        return false;
    if(n==2)
        return true;
    for(int i=2;i<10;++i)
    {
        int a=rand()%(n-2)+2;
        if(modular_exp(a,n,n)!=a)
            return false;
    }
    return true;

ll gcd(ll a,ll b)//求最大公约数
{
    return b?gcd(b,a%b):a;
}
ll multi(ll a,ll b,ll mod)//快速加法求模
{
    ll ret=0;
    while(b)
    {
        if(b&1)
            ret=(ret+a)%mod,b--;
        a=(a+a)%mod;
        b>>=1;
    }
    return ret;
}
ll power(ll a,ll b,ll mod)
{
    ll ret=1;
    a%=mod;
    while(b)
    {
        if(b&1)
            ret=multi(ret,a,mod),b--;
        a=multi(a,a,mod);
        b>>=1;
    }
    return ret;
}
bool miller_rabin2(ll n)
{
    if(n==2)
        return true;
    if(n<2||!(n&1))
        return false;
    ll m=n-1;
    ll cnt=0;
    while(!(m&1))
    {
        ++cnt;
        m>>=1;
    }
    for(int i=0; i<Times; ++i)//Times==10
    {
        ll a=rand()%(n-1)+1;
        ll x=power(a,m,n);
        ll y=0;
        for(int j=0; j<cnt; ++j)
        {
            y=multi(x,x,n);
            if(y==1&&x!=1&&x!=n-1)
                return false;
            x=y;
        }
        if(y!=1)
            return false;
    }
    return true;
}
int main()
{
    srand(time(NULL));
    int n;
    while(cin>>n)
    {
        for(i=2;i<sqrt(n); ++i)//验证素数
            if(n%i==0)
                break;
        if(i<=sqrt(n)||n==1)
            printf("NO\n");
        else
            printf("YES\n");

        for(int i=2;i<n;++i)//方法1求得素数
        {
            if(miller_rabin1(i))
                cout<<i<<" ";
        }
        cout<<endl;
        for(int i=2;i<n;++i)//方法2求的素数
        {
            if(miller_rabin2(i))
                cout<<i<<" ";
        }
        cout<<endl;
        Prime(n);
        cout<<num_prime<<endl;
        for(int i=0;i<num_prime;++i)//线性筛素数
            cout<<prime[i]<<" ";
        cout<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/sdau_fangshifeng/article/details/81348852