素性测试Miller Rabin判质数
文章目的:判断一个大数是否是素数
前置定理:1.所有>2的素数都可以唯一地表示成两个平方数之差 p=a^2-b^2
所以p=(a+b)(a-b) 由于 p是素数 所以 a+b=p,a-b=1;
2.费马小定理a^(p-1)≡1(mod p) (gcd(a,p)=1;)
正题:我们根据a^(p-1)≡1(mod p)可以得到一个逆命题(伪)当a<p时如果满足a^(p-1)mod p=1,那么p是一个素数,但经过打表发现是假的。
但只是少数合数满足这个条件,所以我们能够想到,用a=2~m来逐个排除,满足a^(p-1)mod p=1的不一定是素数,但不满足的一定不是,只要其中一个a不满足就一定不是了
But,有些恶心素数仍然满足,所以我们可以用一个新定理 如果p是素数,x是小于p的正整数,且x^2 mod p = 1,要么x=1,要么x=p-1,证明和前置定理1差不多就 x^2-1=py, py=(x+1)(x-1);即p能整除(x+1)(x-1)所以......
然后我们结合不妨将费马小定理和上面的定理:将p-1分解为p-1=d*(2^r),不断地对d进行平方操作,若发现非平凡平方根时即可判断出其不是素数。例如 2^340 mod 341=1---> 2^170 mod 341=1--->2^85 mod 341==32 所以341不是素数
总结
不断地提取指数p-1中的因子2,把p-1表示成d2^r(其中d是一个奇数)。那么我们需要计算的东西就变成了a的d2^r次方除以n的余数。于是,a^(d 2^(r-1))要么等于1,要么等于n-1。如果a^(d 2^(r-1))等于1,定理继续适用于a^(d 2^(r-2)),这样不断开方开下去,直到对于某个i满足a^(d 2^i) mod n = n-1或者最后指数中的2用完了得到的a^d mod n=1或n-1。这样就OK了,但正确率仍然不可100%,但也很高了,建议用8次a来判断
本蒟蒻就说完了,有误请指教
参考文本(https://oi-wiki.org/math/prime/) (http://www.matrix67.com/blog/archives/234)
inline ll ksc(ull x,ull y,ll p){//O(1)快速乘(防爆long long) return (x*y-(ull)((lb)x/p*y)*p+p)%p; } inline ll ksm(ll x,ll y,ll p){//快速幂 ll res=1; while(y){ if(y&1)res=ksc(res,x,p); x=ksc(x,x,p); y>>=1; }return res; } inline bool mr(ll x,ll p){ if(ksm(x,p-1,p)!=1)return 0;//费马小定理 ll y=p-1,z; while(!(y&1)){//一定要是能化成平方的形式 y>>=1; z=ksm(x,y,p);//计算 if(z!=1&&z!=p-1)return 0;//不是质数 if(z==p-1)return 1;//一定要为1,才能继续二次探测//即p能整除(x+1)(x-1) }return 1; } inline bool prime(ll x){ if(x<2)return 0; if(x==2||x==3||x==5||x==7||x==43) return 1;//这里自己看着办 return mr(2,x)&&mr(3,x)&&mr(5,x)&&mr(7,x)&&mr(43,x); }