この記事はで再現されhttps://www.cnblogs.com/zsq259/p/11602175.html
ミラー・ラビン
理由は限られた知識Hastin鶏料理の前の文、食べ物はしたがって、それは特に、言語仕様、唯一の理解ではないかもしれません。
ステップ0
Qの数\(P \)素数かどうか、\(P <= 18} 10 ^ {ある\) 。
単純なアプローチは、強制することである(O(\ SQRT {N \を \)}) 列挙について。
しかし、明らかに揚げました。
だから我々は、ミラー・ラビンを持っています。
ナンセンスの多くを話します...
ステップ1
まずフェルマーの小定理を見て:
場合\(P \)が素数であり、その後のために([1、で\ \ P-1] \) している\(P A ^ {} \当量A(MOD \) \(P)\)
そこである\(1-P ^ {} \当量。1(MOD \) \(P)\)
ここでは、フェルマーの小定理、それを証明するために数学的帰納法を使用します。
明らかに\(A = 1 \)文が真であるとき、
場合は\(= N \)文は真であるとき、
場合\(= N + 1 \ ) がある場合
\((N + 1)^ P \)\(= \ sum_ I = {0}} ^ {P ^ {C_ {P}} I N-PI ^ {} \)(二項定理)
次に加えて\(N ^ {P} \ ) と\(1 \)外側の2つ、
他は、係数有する(私は\、^ {C_ {P}} I [1、P-1] \)\を、それができる\(P \)割り切れます。
そして\(N-P ^ \ N-当量(MOD \) \(P)\) 、
そう\((N + 1)^ {P} \ + N-当量1(MOD \) \(P)\) 、結論が成り立ちます。
そうトピックに戻る数の、場合\(P \) 、プレゼンス\(IN A \ [1、P-1] \) 、\(A ^ {P-は、1} \(MODを\)equiv1ない\ \( P-)\) 、その後、\(のp \)は確かではない素数。
しかし、検出を逃れることができるいくつかは、まだあります、
だから、
ステップ2
プロービング二次!
素数のための\(P \)であれば、\(で\ [1、P-1] \) 、および\(A ^ 2 \ equiv1(MOD \) \(P)\) 、次いで\(= 1 \)または\(1-P = \) 。
証明:
もし\(A ^ 2 \ equiv1(MOD \) \(P)\) 、次いで\(A ^ 2-1 \当量0(MOD \) \(P)\)
それ\(P |(A + 1)(1-A)\。。) 。
ので\(P \)は素数であり、([P-1。1]におけるA \ \)\、場合にのみ、そのよう\(= 1 \)または\(= P-1 \ ) 式が成立したときに。
だから、変えたい\(\)は、他の数に等しい、\(P \)は素数ではありません。
ステップ3
ここで再び、特定の実装について話します。
最初の大きなアイデアは、フェルマーの小定理、途中で次のプロービングの判断です。
番号を確認するには、\(のP- \) 、
セット\(U = P-1 \)は、フェルマーの小定理のに応じて存在する\(A ^ U \当量1(MOD \) \(P)\) 、\(A \で[1、P-1] \ )。
次に\(U \)書かれた\(D * 2 ^ N \ ) 形態、すなわち\((((D ^ 2)^ 2)^ 2)^ 2 {...} \)(N-2番目)
だから、から\(D ^ 2 \)は、第二のプローブを決定することから始まります
最後に、その行にフェルマーの小定理判断。
しかし、時間の複雑さである\(O(LOG_ {\小型2} \) \(P)\) 。
故障率であった(\ \ FRAC。1 {{}}。4 \) 、
次に\(T \)誤り率試験である\(4 ^ { - } T \) 、時間複雑である(O(TLOG _ {\小型2} Pを)\)\、受け入れることができます。
そしてあれば\(N <2 ^ {64} \) 、のみを選択\(A = 2、3、 5、7、11、13、17、19、23、29、31、37 \) 試験することができます。
int128を開くように見える:(コード)
#include <iostream>
#include <cstdio>
#include <cstring>
#define int __int128
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
}
int p[101]={2,3,5,7,11,13,17,19,23,29,31,37};
int T,n,tot=12;
inline int fpow(int a,int b,int p){
int ret=1;
for(;b;a=a*a%p,b>>=1) if(b&1) ret=ret*a%p;
return ret;
}
inline bool Miller_Rabin(int n){
if(n<=2){
if(n==2) return 1;
return 0;
}
int u=n-1;
while(!(u%2)) u>>=1;
int d=u;
for(int i=1;i<tot&&p[i]<n;i++){
int x=p[i];u=d;x=fpow(x,u,n);
while(u<n){
int y=fpow(x,2,n);
if(y==1&&x!=1&&x!=n-1) return 0;
x=y;u<<=1;
}
if(x!=1) return 0;
}
return 1;
}
signed main(){
T=read();
while(T--){
n=read();
if(Miller_Rabin(n)) puts("Yes");
else puts("No");
}
return 0;
}