Evanyou Blog 彩带

  题目传送门

质数判定

题目描述

判定输入的数是不是质数。

输入格式

若干行,一行一个数 x

行数不超过 $1.5 imes 10^4$

输出格式

对于输入的每一行,如果 x是质数输出一行 Y,否则输出一行 N

样例

样例输入

1
2
6
9
666623333

样例输出

N
Y
N
N
Y

数据范围与提示

$1leq xleq 10^{18}$

欢迎hack(如果你不是管理员,可以在题目讨论区发帖)。


  分析:

  Miller_Rabin模板,被卡了好久。

  具体的Miller_Rabin算法博主就不再讲了,注意要考虑到一些细节,然后$LibreOJ$卡时间,不能用$log n$的乘法,需要用快速乘。

  Code:

//It is made by HolseLee on 10th Sep 2018
//LibreOJ#143
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long ll;
ll n,a[6]={2,3,5,7,61,24251};

inline ll mul(__int128 x,__int128 y,__int128 m)
{
    return (__int128)(x*y)%m;
}

inline ll power(ll x,ll y,ll m)

{
    ll ret=1; x%=m;
    while( y ) {
        if( y&1 ) ret=mul(ret,x,m);
        y>>=1; x=mul(x,x,m);
    }
    return ret;
}

inline bool miller_rabin(ll u)
{
    if( u==2 ) return 1;
    if( !(u&1)  || u==1 || u==46856248255981 ) return 0;
    u-=1;
    int cnt=0; ll x,pre; 
    while( !(u&1) ) u>>=1,cnt++;
    for(int i=0; i<=5; ++i) {
        if(n==a[i])return 1;
        if(n%a[i]==0)return 0;
        x=power(a[i],u,n);
        pre=x;
        for(int j=1; j<=cnt; ++j) {
            x=mul(x,x,n);
            if( x==1 && pre!=n-1 && pre!=1 ) return 0;
            pre=x;
        }
        if( x!=1 ) return 0;
    }
    return 1;
} 

int main()
{
    while( scanf("%lld",&n)!=EOF ) {
        if( miller_rabin(n) ) puts("Y");
        else puts("N");
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/cytus/p/9619479.html