试除法:最简单的因数分解算法,从$ 2 $到$ \sqrt n $一个一个试。

试除法(改进):从$ 2 $到$ \sqrt n $挑素数一个一个试。

然而这样复杂度是相当高的。

生日悖论:指如果一个房间里有23个或23个以上的人,那么至少有两个人的生日相同的概率要大于50%。

我们在$ [2,n) $取一个数,该数是$ n $的因子的概率很小.

我们取$ k $ 个数$ x_1,x_2,x_3...x_k $,而取出的 $ k $ 个数中,$ \exists i,j : (x_i-x_j) | n $ 的概率随着$ k $ 增大而增高。

我们有一个更好的办法:

对选取的$ k $ 个数 $ x_1,x_2,x_3...x_k $,不再询问是否存在$ (x_i-x_j) | n $,改为询问 $ gcd(x_i-x_j,n)>1 $ 的情况。

所以,一个简单的策略如下:

1.在区间$[2,n)$ 中随即选取$ k $个数$ x_1,x_2,x_3...x_k $

2.判断是否存在$ gcd(x_i-x_j,n)>1 $ , 若存在,$ gcd(x_i-x_j,n)>1 $ 是$ n $的一个因子。

我们大概需要选取$ n^{\frac{1}{4}}$个数,这可能存不下。

Pollard's Rho 算法

为了解决数太多无法储存的问题,Pollard's Rho 算法之将两个数存在内存里,我们生成并检查这两个数,反复执行这个步骤并希望得到我们想要的数。

我们不断使用一个函数来生成这个序列(有点像随机数),并非所有函数都可以,但有一个神奇的函数可以$ f(x)=(x^2+a)mod n $; $ a $ 可以指定也可以随机。

这个序列显然是存在环的,如何检测环出现呢?

方法一:floyd判环法

floyd判环法:假如两个人$A、B$在环上走,如何知道已经走完一圈呢? 让$B$以$A$两倍的速度走,$B$第一次赶上$A$时,$B$至少走完一圈了

设定$ x=y=x0 $的初始值,进行迭代,每次:$ x=f(x), y=f(f(y)) $ 即:$ x=x_i,y=x_{2i} $

若$ gcd(x−y,n)=1 $,那么继续枚举下一对 $x,y$ 。

若$ gcd(x−y,n)=n $,更换随机函数 f(x)f(x) ,重新进行算法。

否者我们就找到了一个n的非平凡因子 $ d=gcd(x-y,n) $

当 $x==y$时出现循环,此时$x-y=0$,$ gcd(x−y,n)=n $,即为2情况。

LL pollardRho(LL n, int a){
LL x=,y=,d=;
while(d==){
x=(x*x+a)%n;
y=(y*y+a)%n;y=(y*y+a)%n;
d=gcd(abs(x-y),n);
}
if(d==n) return pollardRho(n,a+);
return d;
}

方法二:brent判环法

不同于floyd每次计算$x_i,x_{2i}$进行判断,brent每次只计算$x_i$,当$k$是2的方幂时,$y=x_k$,每次计算$d=gcd(x_k−y,n)$

LL pollardRho(LL n, int a){
LL x=,y=,d=,k=,i=;
while(d==){
++k;
x=(x*x+a)%n;
d=gcd(abs(x-y),n);
if(k==i){y=x;i<<=;}
}
if(d==n)return pollardRho(n,a+);
return d;
}

求全部因子(结合miller-rabin测试)

LL cnt,fact[];
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
LL pollardRho(LL n, int a){
LL x=rand()%n,y=x,d=,k=,i=;
while(d==){
++k;
x=ksc(x,x,n)+a;if(x>=n)x-=n;
d=gcd(x>y?x-y:y-x,n);
if(k==i){y=x;i<<=;}
}
if(d==n)return pollardRho(n,a+);
return d;
}
void findfac(LL n){
if(millerRabin(n)){fact[++cnt]=n;return;}
LL p=pollardRho(n,rand()%(n-)+);
findfac(p);
findfac(n/p);
}

例题:POJ1811

https://files-cdn.cnblogs.com/files/Doggu/Pollard-rho%E7%AE%97%E6%B3%95%E8%AF%A6%E8%A7%A3.pdf

https://blog.csdn.net/qq_39972971/article/details/82346390

https://www.cnblogs.com/book-book/p/6349362.html

Pollard-rho算法[因子分解算法]的更多相关文章

  1. Pollard Rho算法浅谈

    Pollard Rho介绍 Pollard Rho算法是Pollard[1]在1975年[2]发明的一种将大整数因数分解的算法 其中Pollard来源于发明者Pollard的姓,Rho则来自内部伪随机 ...

  2. Pollard rho算法+Miller Rabin算法 BZOJ 3668 Rabin-Miller算法

    BZOJ 3667: Rabin-Miller算法 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1044  Solved: 322[Submit][ ...

  3. 初学Pollard Rho算法

    前言 \(Pollard\ Rho\)是一个著名的大数质因数分解算法,它的实现基于一个神奇的算法:\(MillerRabin\)素数测试(关于\(MillerRabin\),可以参考这篇博客:初学Mi ...

  4. Pollard Rho 算法简介

    \(\text{update 2019.8.18}\) 由于本人将大部分精力花在了cnblogs上,而不是洛谷博客,评论区提出的一些问题直到今天才解决. 下面给出的Pollard Rho函数已给出散点 ...

  5. Miller Rabin素数检测与Pollard Rho算法

    一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...

  6. 大整数分解质因数(Pollard rho算法)

    #include <iostream> #include <cstring> #include <cstdlib> #include <stdio.h> ...

  7. BZOJ 5330 Luogu P4607 [SDOI2018]反回文串 (莫比乌斯反演、Pollard Rho算法)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330 (Luogu) https://www.luogu.org/prob ...

  8. Pollard Rho因子分解算法

    有一类问题,要求我们将一个正整数x,分解为两个非平凡因子(平凡因子为1与x)的乘积x=ab. 显然我们需要先检测x是否为素数(如果是素数将无解),可以使用Miller-Rabin算法来进行测试. Po ...

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

    Pollard-Rho 是一个很神奇的算法,用于在 $O(n^{\frac{1}4}) $的期望时间复杂度内计算合数 n 的某个非平凡因子(除了1和它本身以外能整除它的数).事书上给出的复杂度是 \( ...

随机推荐

  1. 一千行MySQL学习笔记 (转)

    出处:  一千行MySQL学习笔记 /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权 ...

  2. DataX操作指南

    1.DataX介绍 DataX DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL.Oracle.SqlServer.Postgre.HDFS.Hive.ADS.HB ...

  3. springboot添加https

    一.使用JDK工具keytool生成证书 keytool命令详解 https://blog.csdn.net/zlfing/article/details/77648430 keytool -genk ...

  4. 第一个SpringMVC的注解应用

    由于默认的配置文件中支持了注解,所以可以直接编写注解的Controller 将ItcastController加入到SpringMVC容器中: 配置Controller的扫描包

  5. CentOS7部署kettle

    去官网下载kettle, 或者百度网盘下载(nnnk),解压到目录/opt/service/, 解压后的目录是data-integration kettle需要java环境才能运行,因此要安装Java ...

  6. php后门简单检测脚本

    # coding:utf-8 import os import sys import re rulelist = [ '(\$_(GET|POST|REQUEST)\[.{0,15}\]\(\$_(G ...

  7. springboot-异步线程调用

    启动类:添加@EnableAsync注解 @SpringBootApplication @EnableAsync public class Application{ public static voi ...

  8. linux的一些运维操作基本知识

    1 ~/.bashrc 这个可以认为是linux系统的启动项,每次启动的时候都会运行一些这里边的命令: 常见的有: alias rm='rm -i'//修改某些指令: export LD_LIBRAR ...

  9. cmd中subst的使用

    SUBST [drive1: [drive2:]path] drive1:        指定要指派路径的虚拟驱动器.[drive2:]path  指定物理驱动器和要指派给虚拟驱动器的路径. 路径替换 ...

  10. Nginx 的简介

    1. 什么是 nginx :Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数.  2. 正向代理 ...