nefu 120 梅森素数 卢卡斯-莱默素数测试 miller-rabin素数测试 打表

http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=120

1.打表

//梅森素数
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef unsigned long long ULL;
const int a[]={2,3,5,7,13,17,19,31,61};
int main()
{
    int T;
    while(scanf("%d",&T)==1)
    {
        while(T--)
        {
            int n;
            scanf("%d",&n);
            bool flag=false;
            for(int i=0;i<9;i++)
                if(a[i]==n) flag=true;
            if(flag) cout<<"yes"<<endl;
            else cout<<"no"<<endl;
        }
    }
    return 0;
}

2.卢卡斯-莱默素数测试

//梅森素数 卢卡斯-莱默判定法
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=70+5;
LL multi(LL a,LL b,LL k)                                                        //a*b%k     避免溢出所以把乘法变成了加法
{
    LL ret=0;
    while(b)
    {
        if(b&1) ret=(ret+a)%k;
        b>>=1;
        a=(a<<1)%k;
    }
    return ret;
}
int main()
{
    int T;
    while(scanf("%d",&T)==1)
    {
        while(T--)
        {
            int n;
            scanf("%d",&n);
            LL k=1;
            k<<=n;
            k--;                                //得到梅森数
            LL data[maxn];
            data[1]=4;
            for(LL i=2;i<=n-1;i++)
            {
                LL temp=multi(data[i-1],data[i-1],k);
                data[i]=(temp-2)%k;
            }
            if(n==2||data[n-1]==0) cout<<"yes"<<endl;
            else cout<<"no"<<endl;
        }
    }
    return 0;
}

3.miller-rabin素数测试

//Miller素数测试方法
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long LL;
int tim=12;                    //Miller测试次数
LL k;
LL choose()                         //选择基底
{
    return rand()%(k-2)+1;
}
LL multi(LL a,LL b,LL n)                        //a*b%n
{
    LL ret=0;
    while(b)
    {
        if(b&1) ret=(ret+a)%n;
        b>>=1;
        a=(a<<1)%n;
    }
    return ret;
}
LL pow_mod(LL a,LL b,LL MOD)                        //a^b%n
{
    LL res=1;
    while(b)
    {
        if(b&1) res=multi(res,a,MOD);
        a=multi(a,a,MOD);
        b>>=1;
    }
    return res;
}
bool witness(LL a,LL n)
{
    LL m=n-1;
    int j=0;
    while(!(m&1))
    {
        j++;
        m>>=1;
    }
    LL x=pow_mod(a,m,n);
    if(x==1||x==n-1) return false;
    while(j--)
    {
        x=x*x%n;
        if(x==n-1) return false;
    }
    return true;
}
bool miller_rabin(LL n)
{
    if(n<2||n%2==0) return false;
    else if(n==2) return true;
    //做tim次独立的测试
    for(int i=0;i<tim;i++)
    {
        LL a=choose();                  //选择基底
        if(witness(a,n)) return false;
    }
    return true;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        LL n;
        srand(time(NULL));
        scanf("%lld",&n);
        k=1;
        k<<=n;
        k--;
        if(miller_rabin(k)) cout<<"yes"<<endl;
        else cout<<"no"<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37428263/article/details/81141177
今日推荐