Miller-Rabbin 素性测试 和 Pollard_rho整数分解

时间:2022-10-08 18:33:05

今天学习一下Miller-Rabbin  素性测试 和 Pollard_rho整数分解。

两者都是概率算法

Miller_Rabbin素性测试是对简单伪素数pseudoprime测试的改进。

(pseudoprime测试, POJ 3641 pseudoprime numbers

简单伪素数pseudoprime的原理是费马小定理的逆命题。

费马小定理:p是素数,an-1≡1 mod p。

逆命题几乎成立。 满足逆命题叫做以a为基的伪素数。

几乎是因为被证明存在无数多个合数满足逆命题,叫做Carmichael数。Carmichael数的密度极小,1e8范围内只有255个。

(UVa 10006 Carmichael Number

改进的测试方法的原理是欧拉给出的定理。

x2≡1 mod pe,p是奇素数,这个方程只有两个解 x = -1和 x = 1。(还可以用了判断二次剩余

证明可以看算法导论定理31.34

这个定理的逆否命题对2也成立,也就是说模n如果有x2≡1 mod n,x ≠ 1且 x ≠ -1,那么n是合数。

利用这点可以构造一个证明n是合数的过程witness。

bool witness(ll a,ll n)//a是1~n-1范围内随机选取的基。
{
int t = ;
ll u = n-;
while((u&^)) { u>>=; t++; } //计算n-1 = 2^t*d,用于反复平方
ll x = powMod(a,u,n), y;
while(t--){
y = mulMod(x,x,n);
if(y == && x != && x != n-) return true; //如果y = x^2 = 1 mod n 存在 x != 1且 x != n-1说明是合数
x = y;
}
return x != ;
}

对于Carmichael数这种测试方法也有效,证明这里略过。

出错概率大概是1/2^k,k是测试次数。

int64的乘法可能会溢出,需要自行编写函数mul_mod()完成计算。

Pollard_rho整数分解

Pollard_rho是用f(x) = x^2 + c mod n 产生伪随机序列。d = gcd(y-x,n),如果 d > 1,那么 y - x是 n的一个因子q的k倍,然后再做分解就好。

循环大概会在期望Θ(sqrt(p))的复杂度找到n的一个因子p。如果不存在的话会比较慢,所以先用MillerRabbin判断一下是不是素数n。

p≤sqrt(n), 所以有Θ(n^(1/4))。

证明没看懂。。。(似乎是k q有 sqrt(n)个, 而 y - x 的组合命中 一个 k q 期望 也是要 sqrt(n)次

序列是伪随机,c设置的不好,可能找不到因子就循环了,可以用flody判圈法。

(一般使用的是改进过的flody判圈法, y的步进是倍增的。

具体代码见POJ GCD & LCM inverse

参考资料:

《算法导论第31章 数论算法》

https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm

Pollard_rho

http://wenku.baidu.com/link?url=oaiwXWqJcPfeSfWtT7et-A3g9sFDSI3OjvmToU23rBJXwlToKaikoSrCnwRoozX24YmxDsVdwubMdu0xy3bMqI-ijcReKgMtdIlR6pEowd_