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

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;
    }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值