[快速因数分解]Pollard's Rho 算法

来源:互联网 发布:devcpp使用教程c语言 编辑:程序博客网 时间:2024/04/28 16:13

Description

给出一个数N,求N其中的一个因数。(1和N外)
N<=10^18

好玄学的一个东西。
首先,如果直接暴力,根号n肯定过不了。
在讲正解之前,我们先来讲讲道理。

生日悖论

在n个人中,生日(月份和日期)两两不同的概率是多少。
一年取365天
很显然,第1个人的生日可以取365365
第2个人为364365
以此类推。
总概率为

i=0n1365i365

代入n,发现当n=23的时候,概率就已经小于50%了。
也就是说,普通的一个班里面有至少50%的概率有两个人的生日在同一天。
是不是很玄学?233
所以才叫悖论嘛~

Pollard’s Rho 算法

知道这个东西有什么卵用吗?
我们先稍稍修改一下这个问题,
从[1~1000]中选出两个数i,j,|i-j|=l的概率是多少。
大约为1500
那么如果我们选择k个数,x1~xk,使得其中有两个数的差为l的概率呢?
写个暴力计算下
当k=30时,概率就超过了50%
k=100时,基本已经100%了!
那么我们可以运用这个结论,每次rand()多一个数,判断一下,是否有差值是N的因数。
效率大大滴提高了!
从某一篇文章上看到,大约是O(N14)
玄学♂

不过,rand可能出现神奇的东西。手打一个
f(x)=x*x+a %N
但是,在有些数据下,它会死循环。
那么我们只需要找出环,重新rand出a,再做一次。
判环可以用Floyd的聪明又有趣的方法。
A和B在同一个环上跑,怎么知道A已经跑了一圈?
我们让B的速度是A的2倍,那么当B追上A的时候A已经跑了一圈了~
玄学♀

Code

ll f(ll x) {return (mult(x,x)+t)%N;}for(;!q;t=rand()%100) {    a=t;b=f(t);    while (a!=b) {    a=f(a);b=f(f(b));    ll k=gcd(abs(a-b),N);    if (k>1) {        q=k;p=N/k;break;    }    }}
0 1
原创粉丝点击