Miller Rabin 素数测试
作者:互联网
先说下伪素数的概念,费马小定理的逆不成立的合数成为伪素数,即满足a的x-1mod x=1但不是素数。
通常我们判断奇素数(2肯定是素数)由费马小定理与二次剩余定理得到,1的(x-1)/2=1modx
所以对上述底数a要么为1,要么为-1(取模后)所以我们把x-1进行不断二分,在这些2的m次中要么全为1,要么中间有一个-1,之后全为1,这样条件下,它大概率是素数,在2的64次以内,他人已经为我们找好了检验素数的a,只要全部满足,必为素数。
a: 2, 325, 9375, 28178, 450775, 9780504, 1795265022
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
#include<string.h>
#include<vector>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ll long long
using namespace std;
ll qpow(ll a,ll b,ll p){
ll ans=1;
while(b){
if(b&1)ans=(__int128)ans*a%p;
a=(__int128)a*a%p;
b>>=1;
}
return ans;
}
bool is_prime(ll x){
if(x<3)return x==2;
if(x%2==0)return false;
ll A[]={2,325,9375,28178,450775,9780504,1795265022},d=x-1,r=0;
while(d%2==0)
d/=2,++r;
for(int j=0;j<7;j++){
ll v=qpow(A[j],d,x);
if(v<=1||v==x-1)continue;
for(int i=0;i<r;i++){
v=(__int128)v*v%x;
if(v==x-1&&i!=r-1){
v=1;
break;
}
if(v==1)return false;
}
if(v!=1)return false;
}
return true;
}
int main(){
int t;
cin>>t;
ll n;
while(t--){
cin>>n;
if(is_prime(n))cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
标签:Miller,ll,素数,要么,ans,include,定理,Rabin 来源: https://blog.csdn.net/qq_50812688/article/details/119078674