所谓 pollard-rho,就是泼辣的肉

(逃)

前言

许多题解都把这两个算法放在了一起。
那我也这样办吧!

miller-rabin可以在优秀的时间复杂度内完成对一个数的素性检测。
而pollard-rho则是立足于Miler-rabin之上,可以在 O(n14)O(n^\frac 1 4)O(n41​) 的复杂度内分解出一个合数的非平凡因子。

Miller-rabin

费马定理:若 ppp 为质数,那么 ap≡a(modp)a^p\equiv a\pmod pap≡a(modp),如果 a⊥pa\perp pa⊥p,同时也有 ap−1≡1(modp)a^{p-1}\equiv 1\pmod pap−1≡1(modp)。

那么一个朴素的思想是随便找一个 aaa,看是否有 ap−1≡1(modp)a^{p-1}\equiv1\pmod pap−1≡1(modp)。
但是,费马定理的逆定理并不成立,因此这个算法是很容易挂掉的,事实上,存在一类合数 nnn,对于任意的 a⊥na\perp na⊥n,都有 ap−1≡1(modp)a^{p-1}\equiv1\pmod pap−1≡1(modp),这类数被称为卡迈克尔数。最小的卡迈克尔数为 561561561,已经可以证明,卡迈克尔数的数量是无穷个的。
我们需要更强的判断方法。

二次检测定理:如果 ppp 为质数,那么 x2≡1(modp)x^2\equiv1\pmod px2≡1(modp) 的两个解分别为 x≡1(modp)x\equiv1\pmod px≡1(modp) 和 x≡−1(modp)x\equiv-1\pmod px≡−1(modp)。

证明:移项得 (x+1)(x−1)≡0(modp)(x+1)(x-1)\equiv 0\pmod p(x+1)(x−1)≡0(modp),由于 ppp 是质数,所以要使等式成立,只能是两个括号中的一个等于 000。
反过来,如果对于一个 x≠±1(modp)x\ne\pm1\pmod px​=±1(modp),出现了 x2≡1(modp)x^2\equiv 1\pmod px2≡1(modp),那么 ppp 一定不是一个素数。

所以,我们考虑对于所有的奇素数 ppp(222 可以特判),p−1p-1p−1 都可以写成 a⋅2k(a%2=1,k>0)a\cdot 2^k(a\%2=1,k>0)a⋅2k(a%2=1,k>0) 的形式,那么我们就可以把原来的式子变一下形:
xp−1≡1(modp)xa⋅2k≡1(modp)(xa⋅2k−1)2≡1(modp)x^{p-1}\equiv1\pmod p\\x^{a\cdot2^k}\equiv 1\pmod p\\(x^{a\cdot2^{k-1}})^2\equiv 1\pmod pxp−1≡1(modp)xa⋅2k≡1(modp)(xa⋅2k−1)2≡1(modp)
那么就出现了一个可以使用二次探测的形式,我们检查一下 xa⋅2k−1x^{a\cdot2^{k-1}}xa⋅2k−1 是否为 ±1\pm1±1 即可。同时,注意到,如果 k>1k>1k>1 且 xa⋅2k−1x^{a\cdot2^{k-1}}xa⋅2k−1 依然等于 111,那么我们可以递归的进行多次二次探测。

虽然正确性大大提高,这个算法依然是一个概率性检测。我们需要多选取几个 aaa,多次检测才能尽可能的保证其正确性。
实践表明,选取前 121212 个质数已经可以保证 n=264n=2^{64}n=264 以内的正确性了。

注意! 费马定理的前提是 a⊥pa\perp pa⊥p,因此,如果 a=pa=pa=p,会把 ppp 错判成合数,需要特判。

int p[13]={0,2,3,5,7,11,13,17,19,23,29,31,37};
bool check(ll a,ll n){  ll k=n-1;if(ksm(a,k,n)!=1) return false;while(1){k>>=1;ll x=ksm(a,k,n);if(x!=1&&x!=n-1) return false;if(x==n-1||(k&1)) return true;}
}
bool prime(ll n){//miller-rabinif(n<3||((n&1)==0)) return n==2;for(int i=1;i<=12;i++){if(p[i]==n) return true;if(!check(p[i],n)) return false;}return true;
}

Pollard-Rho

感谢 _slb\text{\_slb}_slb 和 Asta\text{Asta}Asta!
(不会打红黑名凑活看吧)
既然弗洛伊德找环慢的一批,我就不浪费大家时间,直接讲倍增优化了。毕竟这两个算法前后也并不构成前置关系。(甚至感觉倍增更好理解一些)

考虑一个随机数列:
xi≡xi−12+c(modp)x_i\equiv x_{i-1}^2+c\pmod pxi​≡xi−12​+c(modp)
其中 ccc 为一个随机常数。
这是一个很差的随机数实现,只要某一项出现相同,就会陷入循环节。
生日悖论告诉我们,它的循环节期望长度是 O(n)O(\sqrt n)O(n​) 。
这个函数会在有限次后进入循环节,也就是:


这个样子(图源:oiwiki-分解质因数)

假设我们已经通过某种方式(比如 Miller-rabin) 知道了 nnn 是一个合数。
那么一定存在一个 mmm,满足 m∣n,m≤nm|n,m\le \sqrt nm∣n,m≤n​。
那么这个函数在 modm\bmod \space mmod m 的意义下的期望循环节长度就是 O(m)≤O(n14)O(\sqrt m)\le O(n^\frac 1 4)O(m​)≤O(n41​)。

modn\bmod \space nmod n 意义下的环和 modm\bmod \space mmod m 意义下的小环是同时存在的,大概就长成这样:

不难看出,这张图是我手画的。
其中黑线代表的是 modn\bmod\space nmod n 意义下的环(暂且叫它大环),红线是 modm\bmod \space mmod m 意义下的环(暂且叫它小环)。
那么我们要做的就是找到这个红线的环。
如何寻找?gcd⁡\gcdgcd!
在函数上设置两个指针 sss 和 ttt,先让 ttt 不断的往后移(具体而言,就是令 t←f(t)t\gets f(t)t←f(t))。然后计算 gcd⁡(∣t−s∣,n)\gcd(|t-s|,n)gcd(∣t−s∣,n)。若 gcd⁡(∣s−t∣,n)>1\gcd(|s-t|,n)>1gcd(∣s−t∣,n)>1,说明找到了一个 nnn 的因子(或者说 s−ts-ts−t 恰好是一个 modm\bmod \space mmod m 意义下的环),就返回结果。

但是我们发现,如果 sss 在 f(0)f(0)f(0) 点处待着不动弹,可能 ttt 怎么移动都没有用啊…
所以我们还需要时不时的把 sss 往前挪一挪。

还有一个问题:虽然我在这里把两个环叫做大环、小环,但是它们的大小关系只是在期望的意义下,也就是说,是有可能存在 modn\bmod\space nmod n 意义的环比 modm\bmod\space mmod m 的环要小的。
这个时候,两个指针还没绕完小环,就把大环绕完了。那么具体来说会出现什么情况?就是 ∣t−s∣≡0(modn)|t-s|\equiv0\pmod n∣t−s∣≡0(modn),这个时候 gcd⁡(0,n)\gcd(0,n)gcd(0,n) 会直接返回 nnn,那么这个时候我们就重新选择 ccc,重新跑就可以了。少侠请重新来过!

具体实现上,我们发现每次都求一遍 gcd⁡\gcdgcd 慢的一批,怎么办?我们可以把每次得到的 ∣s−t∣|s-t|∣s−t∣ 都结果累乘再一起,隔一段时间一起算就可以啦!
累乘在一起太大了怎么办?没关系,伟大的欧几里德告诉我们: gcd⁡(a,n)=gcd⁡(amodn,n)\gcd(a,n)=\gcd(a\bmod n,n)gcd(a,n)=gcd(amodn,n),所以过程中取模就可以了。
那么我们具体要隔多长时间呢?间隔太短可能没啥效果,间隔太大可能明明早都出现了可以返回的结果,但你的代码还在傻傻的移动 ttt 指针,反而变得很慢。为了和倍增的实现更好的适应,我们最好选择形如 2k−12^k-12k−1 的间隔,而事实是:间隔设为 127127127 口感最佳!

说了这么多,总于可以请出我们泼辣的肉的完整代码了!=v=

ll PR(ll n){//pollard-rhoc=rand()%(n-1)+1;ll s(0),t(0);ll val(1);for(int goal=1;;goal<<=1,s=t,val=1){//倍增for(int stp=1;stp<=goal;stp++){t=f(t,n);val=val*Abs(t-s)%n;if(stp%127==0){ll d=gcd(val,n);if(d>1) return d;}}ll d=gcd(val,n);if(d>1) return d;}
}
ll findfactor(ll x){ll p=x;while(p>=x) p=PR(x);//多次寻找return x;
}

模板:Miller-RabinPollard-Rho(数论)相关推荐

  1. 模板:BSGS(数论)

    所谓 BSGS,就是北上广深. (逃) BSGS 给出 a,b,pa,b,pa,b,p,请处出满足 ax≡b(modp)a^x\equiv b\pmod pax≡b(modp) 的最小非负正数解或者报 ...

  2. 洛谷P2181答案C语言,洛谷P2181 对角线(组合数)

    题目描述 对于一个N个定点的凸多边形,他的任何三条对角线都不会交于一点.请求楚图形中对角线交点的个数. 例如,6边形: 输入输出格式 输入格式: 第一行一个n,代表边数. 输出格式: 第一行输出交点数 ...

  3. 素数判定质因数分解(数论)(Miller Rabin)(Pollard Rho)

    太玄学了! 我真的被概率的魅力折服了.此前我认为1便是1,0.9999999999-便是0.9999999999-. 但实际上它们有着千丝万缕的关系. 试想,如果一件事发生的概率是0.99999999 ...

  4. 数学--数论--随机算法--Pollard Rho 大数分解算法(纯模板带输出)

    ACM常用模板合集 #include <bits/stdc++.h> using namespace std; typedef long long ll; ll pr; ll pmod(l ...

  5. 线性求逆元模板_ACM 数论基本模板

    ACM 数论基本模板 1.欧几里得 求最大公约数,最小公倍数 (1)递归的写法:int gcd(int a,int b) {return b?gcd(b,a%b):a;} (2)辗转相除法: int ...

  6. 【模板篇】数论大杂烩~

    离省选已经不剩几天了, 然而自己还是啥也不会, 所以就临阵磨枪刷一刷板子, 万一用上了就赚到了~~ 这一篇就写写数论?(希望只考到自己打的板子然而这是不可能的←_← 尽量不压行吧, 能写得好懂点就写得 ...

  7. GCD and LCM Aizu - 0005(辗转相除)+GCD LCM Inverse POJ - 2429(java或【Miller Rabin素数測试】+【Pollar Rho整数分解】)

    题目:GCD and LCM Aizu - 0005 Write a program which computes the greatest common divisor (GCD) and the ...

  8. 亿些模板【数论数学】

    文章目录 前言 数论数学模板 GCD exgcd 快速幂 线性推逆元 线性推逆元(非连续) 逆元求组合数 矩阵乘法 线性筛素数-埃氏筛 线性筛素数-线性筛 线性筛欧拉-埃氏筛 线性求欧拉 龟速乘 FF ...

  9. [原创]数论个人模板

    作为一个ACMer不可能没有自己的模板,并不是别人的模板你都能看的懂,所以有自己的模板很重要,下面是我自己一边培训一边整的数论模板,内容很少都是一些数论基础模板(毕竟不是大牛),但是此博客会一直更新的 ...

最新文章

  1. 为什么要用OKR?OKR在什么情况下用?
  2. WINDOWS 蓝屏错误代码说明一览表
  3. 周四话运营:如何提高用户留存?
  4. Windows下MetaMap工具安装
  5. SVM支持向量机详解
  6. 利用python爬虫(part1)--urllib.request模块
  7. elasticsearch例子(crud + 分页)
  8. [Lydsy1806月赛] 最长公共子序列
  9. linux创建环境变量有什么用,环境变量和shell变量到底有什么区别呢?
  10. 思科上海被裁员人均赔偿100万?官方回应:大裁员消息不实,中国业务发展不顺为真...
  11. 免费升级win10系统方法
  12. CI和Smarty整合并且前后台加载不同配置文件使前台应用Smarty缓存后台不应用
  13. STM32并口驱动AD9854——HAL库
  14. 钉钉机器人V1使用说明
  15. Ubuntu 20.04修改ip地址
  16. 小程序如何推广?小程序有哪些推广方式?
  17. 九宫八阵图之虐翼阵——网闸
  18. 四、RNN模型 与 NLP应用 —— Stacked RNN
  19. webpack 降级
  20. java 网络编程详细解析

热门文章

  1. lisp正负调换_坐标提取lisp程序
  2. vue路由上的#/怎么去掉_如何去掉vue路由中的#
  3. SimpleXMLRPC_python xmlrpclib SimpleXMLRPCServer 模块
  4. 硬件加速下webview切换闪屏_网页渲染性能优化 —— 性能优化下
  5. 计算机基础知识教案1,计算机基础知识教案一
  6. 云南河道 kml文件_处理能力提升 4 倍 ,大疆智图 4 天完成 5 公里河道建模
  7. 7-48 银行排队问题之单窗口“夹塞”版 (30 分)(思路和详解+map做法)来呀Baby!
  8. 一般动态规划问题合集(Leetcode题解-Python语言)
  9. 二叉树层序遍历(广度优先搜索)基础概念与经典题目(Leetcode题解-Python语言)
  10. [JavaWeb-Bootstrap]Bootstrap概述