【快速因数分解】Pollard's Rho 算法

算法目的

给一个数n,快速提取n的一个因数。

算法根据:生日悖论

讲生日悖论之前,先看一个东西。
给出[1…1000]的数,从中任意选出一个数为k的概率是 1 1000 1\over 1000 10001
但是假如选出两个数p,q要求他们的差值为k,就是|p-q|=k的概率大概是 1 500 1\over 500 5001,因为要取绝对值。
继续向下,选出l个数,使他们之间有两个数的差值为k,那么概率会随l的变大而变大,最终会趋近于1。
接下来是生日悖论:
我们随机选择一名学生,他的生日为 4 月 1 日的概率为 [1…365]
这相当于我们在[1…365]中随机选取一个数,该数为 90 的概率是多少?
那么我们又回到了上面那个问题。
我们随机选取 k(k≥ 2)个人 ,他们的生日相同的概率是多少(就是差值为0)?
可以直接用公式计算 p = P 365 k 36 5 n p={P_{365}^k\over{365^n}} p=365nP365k
通过计算
我们可以看到,k = 10 的时候大概有 11%的可能性存在两个人生日相同的情况,
而 k = 23 时,可能性提高至50%,假如一个班级总共有57个人,而l=57时的可能性已达到99%,几乎可以肯定地说,一个班级里必定有两个同学的出生日期是相同的,而这么多年的求学生涯过来了,这个概率“似乎”是不正确的,这便是悖论了(这个被称为悖论的原因也是因为人为直观感觉的概率和实际概率不同)。

Pollard’s Rho 算法

那么竟然有了这个玄学的悖论,我们就可以随机的快速分解n了,2333。
有一个随机函数f(x)=(x*x+d)%n,d=rand()。然后每次随机出来的数和上一次随机出来的数的差值与n去一个最大公因数,然后判断一下就好了。
但是假如一直找不到符合的数然后死循环了怎么办。
我们可以用Floyd发明的机智判环算法,因为我每次a=f(a),再找一个b=f(f(b)),如果有一个时刻a=b那么就退出循环,因为b是以两倍的速度走得,当b追上了a,那么b至少已经走完一圈了。
复杂度O( n 1 4 n^{1\over 4} n41),看上去O(玄学)。

Code

随机函数f

ll f(ll x){
    int u=rand();
    return (cheng(x,x,n)+po)%n;
}

Pollard’s Rho 算法

a=0;
    b=1;
    po=rand()%n+1;
    while(1){
    	a=b=rand()%n+1;
	    while(1){
	        a=f(a);
	    	b=f(f(b));
	    	if(a==b)break;
	    	ll ui=abs(b-a);
	    	ll tt=gcd(ui,n);
	    	if(tt==1||tt==n)continue;
	    	if(tt>1){
			    p=tt;
			    break;
			}
		}  
		po--;
		if(p)break;
    }
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页