题意:1e5个(1e18)的数,分别判断它们是不是质素。
题解:Miller Rabin素数测试(费马小定理,二次探测)
- 当被测试数在某一个范围内时,我们可以通过选取适当的测试底数让 MillerRabin 素数测试对于这个范围内的每一个数都能够正确地得出结果。下面是节选自 维基百科 的选取 a的方式。
- 当 N<4,759,123,141选取 a=2,7,61即可确保算法得出正确结果。
- 当 N<3,825,123,056,546,413,051≈3∗10^18选取 a=2,3,5,7,11,13,17,19,23即可确保算法得出正确结果。
-
当 N<18,446,744,073,709,551,616=2^64选取 a=2,3,5,7,11,13,17,19,23,29,31,37即可确保算法得出正确结果
#include<bits/stdc++.h>
#define ll long long
#define i128 __int128
using namespace std;
ll n;
int primes[19]={2,3,5,7,11,13,17,19,23,29,31,37};
ll poww(ll a,ll b,ll c){
ll ans=1;i128 base=a;
while(b){
if(b&1)ans=ans*base%c;
base=base*base%c;
b>>=1;
}
return ans;
}
bool miller_rabin(ll n){
for(int i=0;i<=8;i++){
if(primes[i]==n)return 1;
else if(primes[i]>n)return 0;
ll t=poww(primes[i],n-1,n),x=n-1;
if(t!=1)return 0;
while(t==1&&x%2==0){
x/=2;
t=poww(primes[i],x,n);
if(t!=1&&t!=n-1)return 0;
}
}
return 1;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
while(cin>>n){
if(miller_rabin(n))puts("Y");else puts("N");
}
return 0;
}