首页 > 编程语言 >Pollard-Rho 分解算法学习笔记

Pollard-Rho 分解算法学习笔记

时间:2023-07-08 18:55:27浏览次数:50  
标签:right cdot times Pollard 算法 Rho mod left equiv

Pollard-Rho 分解算法

Pollard-Rho 算法是一种用于快速找到\(n\)的一个非平凡约数的方法。

生日悖论

在不少于\(23\)个人中至少有两人生日相同的概率已经大于\(50\%\)。

更一般的形式,随机选取在\(\left[ 1,N \right]\)范围内的整数,期望到第\(O(\sqrt{N})\)个出现重复。

用下面的方法可以简单估计一下。

\[\begin{aligned} &P\left( A \right) =1-\frac{n}{n}\times \frac{n-1}{n}\times \cdots\times \frac{n-k+1}{n}\ge \frac{1}{2} \\ &\Leftrightarrow\left( 1-\frac{1}{n} \right) \times \left( 1-\frac{2}{n} \right) \times \cdots\times \left( 1-\frac{k-1}{n} \right) \le \frac{1}{2} \\ &\text{根据不等式} 1+x\le e^x \\ &\Leftrightarrow\left( 1-\frac{1}{n} \right) \times \left( 1-\frac{2}{n} \right) \times \cdots\times \left( 1-\frac{k-1}{n} \right) \le e^{-\frac{k\cdot (k-1)}{2\cdot n}} \le \frac{1}{2} \\ &\Leftrightarrow k\ge \sqrt{2\cdot n\cdot \ln 2} \end{aligned} \]

Miller-Robin 素性测试

由于Pollard-Rho是用来寻找非平凡因子的,我们需要提前判断待分解数是否为素数。

费马小定理

若正整数\(a,p\)满足\(\left( a,p \right) =1\),则有\(a^{p-1}\equiv 1 \left(\mod p\right)\)

  • proof:
    显然\(\left\{ 0,1,2, \ldots ,p-1\right\}\)是\(p\)的一个完全剩余系。
    \(\left\{ 0\cdot a,1\cdot a,2\cdot a, \ldots ,(p-1)\cdot a\right\}\)也是\(p\)的一个完全剩余系。
    否则假设\(\exists i,j \subseteq \left\{ 0,1,2, \ldots ,p-1 \right\},i> j,i\cdot a\equiv j\cdot a (\mod p )\)那么\((i-j)\cdot a\equiv 0 (\mod p)\)而\(\left( a,p \right) =1\)所以\(i\equiv j (\mod p)\)出现矛盾。
    因此有$1\times 2\times \cdots \times (p-1)\equiv 1\cdot a\times 2\cdot a\times \cdots\times (p-1)\cdot a\equiv 1\times 2\times \cdots\times (p-1)\times a^{p-1}\left( \mod p \right) \Rightarrow a^{p-1}\equiv 1\left( \mod p \right) $

但遗憾的是,费马小定理的逆命题并不成立,例如$2^{340}\equiv 1\left( \mod 341 \right) $但\(341=11\times 31\)是个合数。

我们只能用费马小定理来判断一个数\(n\)是合数,若存在一个正整数\(a\)满足\(a^{n-1}\neq 1 \left( \mod n \right)\)则我们可以知道\(n\)一定是一个合数。这也是费马素性测试的内容,每次选取一个正整数\(a\)验证\(n\)的素性。

我们不总能通过增加参与测试的\(a\)的数量来提高正确率。因为存在一种数对$\forall b\subseteq \mathbb{N}^* ,(b,n)=1,b^{n-1}\equiv q\left( \mod n \right) $这种数被称为卡迈克尔数,例如\(561=3\cdot 11\cdot 17\)就是一个卡迈克尔数。\((b,561)=1\Rightarrow (b,3)=(b,11)=(b,17)=1\Rightarrow b^2\equiv 1\left( \mod 3 \right)\quad b^{10}\equiv 1\left( \mod 11 \right)\quad b^{16}\equiv 1\left( \mod 17 \right) \quad\Rightarrow\quad b^{560}\equiv (b^2)^{280}\equiv 1\left( \mod 3 \right) \quad b^{560}\equiv (b^10)^{56}\equiv 1\left( \mod 11 \right) \quad b^{560}\equiv (b^16)^{35}\equiv 1\left( \mod 17 \right) \quad \Rightarrow b^{560}\equiv 1\left( \mod 561 \right)\)

二次探测定理

若\(p\)是一个素数,则\(x^2\equiv 1\left( \mod p \right)\)的解只能是\(x\equiv1\left( \mod p \right) \quad x\equiv-1\left( \mod p \right)\)。

  • proof:
    \(x^2\equiv1\left( \mod p \right)\Rightarrow (x+1)\cdot (x-1)\equiv 0 \left( \mod p \right) \Rightarrow p| (x+1)\cdot (x-1)\Rightarrow p|x+1 \quad || \quad p|x-1\)

米勒检验

我们可以在费马素性测试的基础上利用二次探测定理进行进一步测试,如果\(b^{n-1}\equiv 1(\mod n)\)且\(n\)为奇数,则检验\(b^{\frac{n-1}{2}}\equiv -1\)是否成立,若成立则认为\(n\)通过以\(b\)为基的米勒检验,若成立\(b^{\frac{n-1}{2}}\equiv 1\)则继续检验\(b^{\frac{n-1}{4}}\)。

令\(n\)是一个正整数,满足\(n>2,n-1=2^s\cdot t\),其中\(s\)是一个非负整数,\(t\)是一个奇正整数。称\(n\)通过以\(b\)为基的米勒检验,如果有\(b^t\equiv 1(\mod n)\)或者\(b^{2^j\cdot t}\equiv -1(\mod n)\)对某个\(j\)成立,其中\(1\leq j\leq s-1\)。

数学家们已经证明,若\(n\)是一个奇正整数,那么最多有\(\frac{n-1}{4}\)个\(b\),其中\(1\leq b \leq n-1\),使得\(n\)能够通过以\(b\)为基的米勒检验。这说明如果随机选取\(k\)个正整数作为基,若\(n\)是一个合数,他通过所有\(k\)次米勒检验的概率仅为\(\left(\frac{1}{4}\right)^k\)。

可以验证,在\(2^{64}\)范围内,选取\(2,3,5,7,11,13,17,19,23,29, 31,37\)作为基,可以确定性的验证一个正整数是否为素数。

Pollard-Rho分解

根据生日悖论,我们随机的选取\(\left[ 1,N \right]\)之间的正整数,对于\(N\)的最小素因子\(p\),大约在\(\sqrt{p}\)个数之后会出现两个数在模\(p\)意义下相等。

经验表明,在Pollard-Rho算法中选取,\(x_{k+1}\equiv x_k^2+c(\mod n)\)作为随机数生成器有非常好的表现。

下面的图可以直观的感受到Rho是什么意思

Rho

这说明如果\(x_i\equiv x_j(\mod p)\)则利用\(\operatorname{gcd}\left( \left\vert x_i-x_j \right\vert ,n \right)\)即可求出\(n\)的一个非平凡约数,如果不幸\(x_i=x_j\)那么会导致分解失败,然而事实上,由于\(p\leq\sqrt{n}\)模\(p\)的环远小于模\(n\)的环,分解失败的概率极小,失败之后只需要更换随机数生成器的种子再次尝试分解。

那么如何找到这个环呢,记录出现过的数,并在里面查找是不够优秀的,因为还要算上查找的时间复杂度。我们可以引入两个变量\(x,y\),\(x\)每次走一步,\(y\)每次走两步,即\(x_{new}=x^2+c\quad y_{new}=(y^2+c)^2+c\)每次检验\(\operatorname{gcd}(\left\vert x-y \right\vert ,n)\),经过环长步之后\(x,y\)总能相遇。

但是每次都求\(\operatorname{gcd}\)有点浪费时间,总的时间复杂度是\(O(n^{0.25}\cdot \log_2n)\)这边有一个小技巧就是把连续\(lim\)步的\(\left\vert x-y \right\vert\)相乘再做一次\(\operatorname{gcd}\),取\(lim=O(\log_2n)\)就可以优化掉一个\(log\)。

另外Pollard-Rho往往在分解拥有大质因数的正整数时比较有效,在实际应用中可以先用试除法分解掉较小的质因子再用Pollard-Rho分解。

code:【模板】Pollard rho 算法

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#define int long long

using namespace std;

const int d[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};

int prime[200005], a[1000005], n, cnt = 0, div1[1005][2];

int gcd(int o, int p) { return (!p) ? o : gcd(p, o % p); }

int mi(__int128 o, int p, int mo) {
    __int128 yu = 1;
    while (p) {
        if (p & 1) yu = yu * o % mo;
        o = o * o % mo;
        p >>= 1;
    }
    return yu;
}

bool test(int o, int p) {
    int yu = p - 1;
    if (mi(o, yu, p) != 1) return 0;
    while (!(yu & 1)) {
        yu >>= 1;
        if (mi(o, yu, p) == (p - 1)) return 1;
    }
    return mi(o, yu, p) == 1;
}

bool Miller_Rabin(int o) {
    if (o <= 2) return 1;
    for (int i = 1; i < 12; i++)
        if (o == d[i]) return 1;
    for (int i = 0; i < 12; i++)
        if (!test(d[i], o)) return 0;
    return 1;
}

int Pollard_Rho(int n) {
    int x1 = 1ll * rand() * rand() * rand() * rand() % n + 1, y = x1,
        c = rand() + 1;
    for (int lim = 1;; lim = min(lim << 1, 128ll)) {
        int cnt = 1;
        for (int i = 1; i <= lim; i++) {
            x1 = (__int128)x1 * x1 % n + c;
            y = (__int128)y * y % n + c;
            y = (__int128)y * y % n + c;
            cnt = (__int128)cnt * (x1 - y) % n;
        }
        int yu = gcd(cnt, n);
        if (yu > 1) return yu;
    }
    return n;
}

signed main() {
    srand((unsigned)time(NULL));
    for (int i = 1; i <= 100000; i++) a[i] = 0;
    for (int i = 2; i <= 100000; i++) {
        if (!a[i]) prime[++cnt] = i;
        for (int j = 1; (j <= cnt) && (prime[j] * i <= 100000); j++) {
            a[prime[j] * i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    int T;
    cin >> T;
    while (T--) {
        int n, s0 = 0;
        scanf("%lld", &n);
        if (Miller_Rabin(n)) {
            printf("Prime\n");
            continue;
        }
        for (int i = 1; i <= cnt; i++) {
            if (n % prime[i] == 0) {
                s0++;
                div1[s0][0] = prime[i];
                div1[s0][1] = 0;
                while (n % prime[i] == 0) {
                    n /= prime[i];
                    div1[s0][1]++;
                }
            }
        }
        while (!Miller_Rabin(n)) {
            int yu = Pollard_Rho(n);
            n /= yu;
            if (yu > n) swap(n, yu);
            if (yu > 1) {
                div1[++s0][0] = yu;
                div1[s0][1] = 1;
                while (n % yu == 0) div1[s0][1]++, n /= yu;
            }
        }
        if (n > 1) div1[++s0][0] = n, div1[s0][1] = 1;
        int ans = 0;
        for (int i = 1; i <= s0; i++) ans = max(ans, div1[i][0]);
        printf("%lld\n", ans);
    }
    return 0;
}

标签:right,cdot,times,Pollard,算法,Rho,mod,left,equiv
From: https://www.cnblogs.com/clapp/p/17537670.html

相关文章

  • 阵列信号处理及matlab仿真-------波束形成算法基础知识以及MMSE、MSNR和LCMV的MATLAB
    上一篇《阵列信号处理及MATLAB仿真-----阵列信号绪论》里面说了阵列信号处理研究的四个主要问题:波束形成技术、空间谱估计、信号源定位、信源分离。接下来我们就波束形成来做一个详细的学习。一、波束形成的定义:首先说一下它的物理意义,阵列天线的方向图是全方向的,但是......
  • 网络2️⃣HTTPS-密钥交换算法
    SSL/TLSHTTPS是在TCP和HTTP之间添加SSL/TLS安全协议,解决HTTP的安全性问题。在HTTP中,通信之前需要进行TLS握手。密钥交换算法:不同密钥交换算法的TLS握手流程不同。RSA:简单,但存在前向安全问题(如果服务端私钥泄漏,过去被第三方截获的所有TLS通讯密文都会被......
  • 【算法】根据二叉树的级别返回排序后的元素列表
    根据给定的Node树节点,返回包含按级别排序的树中元素的列表,这意味着根元素位于第一位,然后根子元素(从左到右)位于第二位和第三位,依此类推。1publicclassNode2{3publicNodeLeft;4publicNodeRight;5publicintValue;67publicNode(No......
  • 手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实
    手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实体识别、CypherCheetsheet详细教学等效果预览:1.知识图谱存储方式知识图谱存储方式主要包含资源描述框架(ResourceDescriptionFramework,RDF)和图数据库(GraphDatabase)。1.1资源描述框......
  • 42. 查找算法
    一、线性查找算法  线性查找是逐一比对,发现有相同值,就返回下标,否则返回-1。这里,我们实现的线性查找是找到一个满足条件的值就返回。/***@brief线性查找**@paramA待查找的数组*@paramN数组的长度*@paramvalue待查找的元素*@returnint如果找到返回......
  • 游戏AI-寻路-A*寻路算法
    算法介绍:作用:在一个图中,提供一个起点A与一个终点B,给你找出一条估算出来较短的路时间复杂度:n*log(m),n表示图中的节点数,m表示总边的数量时间复杂度分析:一般游戏中的图是一个二维矩阵,所以每个点的方向也就上下左右这么几个,所以每个点枚举方向的时间为常数虽然复杂度为:n*lo......
  • 数据结构与算法(一)
    需要点Java编程基础常见的数据结构栈(Stack):栈是一种特殊的线性表,它只能在一个表的一个固定端进行数据结点的插入和删除操作。队列(Queue):队列和栈类似,也是一种特殊的线性表。和栈不同的是,队列只允许在表的一端进行插入操作,而在另一端进行删除操作。数组(Array):数组是一种聚合数据......
  • C/C++数据结构与算法课程设计[2023-07-06]
    C/C++数据结构与算法课程设计[2023-07-06]数据结构与算法课程设计一、课程设计的目的、要求和任务 本课程设计是为了配合《数据结构与算法》课程的开设,通过设计完整的程序,使学生掌握数据结构的应用、算法的编写等基本方法。1.课程的目的(1)使学生进一步理解和掌握课堂上所学......
  • 万能欧几里得算法学习笔记
    万能欧几里得算法万能欧几里得算法用于解决一类与\(\left\lfloor\frac{p\cdotx+r}{q}\right\rfloor\)有关的和式求解问题,例如类欧几里得算法中提到的和式就属于此类问题。但万能欧几里得算法从几何意义出发能处理更广泛的和式类型。例如\(\sum_{x=0}^{l}A^xB^{\left\lfloor\f......
  • 常用算法记录
    二叉树遍历https://leetcode.cn/problems/binary-tree-preorder-traversal/solutions/87526/leetcodesuan-fa-xiu-lian-dong-hua-yan-shi-xbian-2/递归解法前序遍历publicstaticvoidpreOrderRecur(TreeNodehead){if(head==null){return;}......