【概述】

整数分解目前仍是世界级难题,是非常重要的研究方向,其有很多种算法,性能上各有差异,本文仅介绍试除法、Fermat 算法、Pollard Rho 算法。

【试除法】

试除法也叫穷举法,是整数分解算法中最简单和最容易理解的算法,但也是效率最低的算法。

试除法是用小于等于 n 的每个素数去试除待分解的整数,如果找到一个数能够整除除尽,这个数就是待分解整数的因子。

试除法一定能够找到 n 的因子,因为它检查 n 的所有可能的因子,所以如果这个算法失败,也就证明了 n 是个素数,因此,试除法也常用来判断一个数是不是质数。

bool judge(int n)
{if(n==1)//1不是一个有效因数return false;for(int i=2;i<sqrt(n);i++)//如果能被整除,说明是因数if(n%i==0)retrun true;return false;
}

【Fermat 算法】

Fermat 算法分解大数的效率并不高,但比起试除法要好了很多,且每次计算都是计算出 N 的一个因子,更降低了其效率。

1.费马整数分解

对于一个任意的偶数,我们都可以通过不断提出为 2 的质因子使其最终简化为一个 2 的 n 次幂与一个奇数,因此,任意一个奇数都可以表示为:N=2*n+1

若这个奇数 N 是一个合数,根据唯一分解定理,其一定可以写成 N=c*d 的形式,不难发现,式中 c、d 均为奇数

设:c>d,令 a=(c+d)/2,b=(c-d)/2

可得:N=c*d=a*a-b*b

例如:

2.费马因式分解算法

由于 

因此 

即:

因此,我们可以从  开始枚举,计算  为完全平方数即可求出 a、b,从而可以求得:c=a+b,d=a-b(a>b)

int res[N];
void Fermat(int n)
{int a,b,temp;a=sqrt(n);if(a*a<n)a++;while(1)//y^2=x^2-n{temp=a*a-n;b=sqrt(a*a-n);if(b*b==temp)break;a++;}res[0]=a;//存储a的值res[1]=b;//存储b的值
}

【Pollard Rho 算法】

为进一步提高效率,解决因数太多无法存储的问题,我们有了 Pollard Rho 算法。

1.算法原理

其原理已知待分解的大整数 n,再通过某种方法得到两个整数 a、b,计算 ,直到 p不为1,或 a、b 出现循环为止,然后再判断 p 的值,若 p=n 或 p=1,那么返回的 n 是一个质数,否则返回的 p 是 n 的一个因子,因此我们可以递归的计算 Pollard(p) 与 Pollard(n/p) ,从而求出 n 所有的因子。

实际操作中,我们通常使用函数: 来不断生成伪随机数,用于逐步迭代计算 a、b 的值。

实践中,常取 c=1,再任意取两初值 a、b,即:,在下一次计算中,将 b 的值赋给 a,再次使用上式来计算新的 b 的值,直至 a、b 出现循环。

但是这样判断 a、b 的循环十分麻烦,例如生成伪随机数为:2,10,16,23,29,13,16,23,29,13...时,很难判断循环,因此我们可以采用 Floyd 判环算法来判断循环。

2.Floyd 判环算法实现Pollard Rho 算法

利用多项式 f(x) 迭代出 的值,然后设定 x、y 的初值,选用多项式进行迭代

每次令:,即:

当 x=y 时即出现循环

int GCD(int a,int b)
{return b?GCD(b,a%b):a;
}int Pow_Mod(int a, int b, int m)
{int res=1;while(b){if(b&1)res=(res*a)%m;a=(a*a)%m;b>>=1;}
}long long pollard_rho(long long x, long long c)//寻找一个因子
{long long i=1,k=2;srand(time(NULL));long long x0=rand()%(x-1)+1;//产生随机数x0(并控制其范围在1 ~ x-1之间)long long y=x0;while(1){i++;x0=(Pow_Mod(x0,x0,x)+c)%x;long long gcd=GCD(y-x0,x);if(gcd!=1&&gcd!= x)return gcd;if(y==x0) return x;if(i==k){y=x0;k+=k;}}
}

3.存储大整数的所有因子

组合使用 Pollard Rho 算法与 Miller Rabin 算法,可求出大整数的所有因子。

LL Mult_Mod(LL a,LL b,LL m)//res=(a*b)%m
{a%=m;b%=m;LL res=0;while(b){if(b&1)res=(res+a)%m;a=(a<<=1)%m;b>>=1;}return res%m;
}
LL Pow_Mod(LL a, LL b, LL m)//res=(a^b)%m
{LL res=1;LL k=a;while(b){if((b&1))res=Mult_Mod(res,k,m)%m;k=Mult_Mod(k,k,m)%m;b>>=1;}return res%m;
}bool Witness(LL a,LL n,LL x,LL sum)
{LL judge=Pow_Mod(a,x,n);if(judge==n-1||judge==1)return 1;while(sum--){judge=Mult_Mod(judge,judge,n);if(judge==n-1)return 1;}return 0;
}bool Miller_Rabin(LL n)
{if(n<2)return 0;if(n==2)return 1;if((n&1)==0)return 0;LL x=n-1;LL sum=0;while(x%2==0){x>>=1;sum++;}int times=20;for(LL i=1;i<=times;i++){LL a=rand()%(n-1)+1;//取与p互质的整数aif(!Witness(a,n,x,sum))//费马小定理的随机数检验return 0;}return 1;
}
LL GCD(LL a,LL b)
{return b==0?a:GCD(b,a%b);
}
LL Pollard_Rho(LL n,LL c)//寻找一个因子
{LL i=1,k=2;LL x=rand()%n;//产生随机数x0(并控制其范围在1 ~ x-1之间)LL y=x;while(1){i++;x=(Mult_Mod(x,x,n)+c)%n;LL gcd=GCD(y-x,n);if(gcd<0)gcd=-gcd;if(gcd>1&&gcd<n)return gcd;if(y==x)return n;if(i==k){y=x;k<<=1;}}
}int total;//因子的个数
LL factor[N];//存储所有因子的数组,无序的
void Find_fac(LL n)//对n进行素因子分解,存入factor
{if(Miller_Rabin(n))//是素数就把这个素因子存起来{factor[++total]=n;return;}long long p=n;while(p>=n)//值变化,防止陷入死循环kp=Pollard_Rho(p,rand()%(n-1)+1);Find_fac(n/p);Find_fac(p);
}

【例题】

  • Prime Test(POJ-1811)(Pollard Rho 与 Miller Rabin 求大整数分解):点击这里

数论 —— 整数分解相关推荐

  1. 编程将一个整数分解成一个质因数的连乘积,并打印在屏幕上

    //编程将一个整数分解成一个质因数的连乘积,并打印在屏幕上 //***本题的难点是既要找出质因数,又要保证其连乘为该数 //***需要两个循环,外循环与内循环 /*每个合数 都可以写成几个 质数 相乘 ...

  2. POJ2429 GCDLCM Inverse(整数分解,由GCD+LCM求a,b)

    POJ2429 GCD&LCM Inverse(整数分解,由GCD+LCM求a,b) 分类: 数论 2013-02-12 22:00  180人阅读  评论(1)  收藏  举报 题目:GCD ...

  3. qduoj-这个是道数学题(线段树+整数分解的应用)

    题目链接:https://qduoj.com/problem/825 Description Onion的数论很差,所以作为数学大佬的lb给onion出了一道私家特训提高题 首先给出n,m,代表接下来 ...

  4. VJ 1033 整数分解(版本2)

    描述 整数分解(版本2) 一个正整数可以分解成若干个自然数之和.请你编一个程序,对于给出的一个正整数n(1<=n<=1500),求出满足要求的分解方案,并使这些自然数的乘积m达到最大. 例 ...

  5. 7-37 整数分解为若干项之和(20 分)

    7-37 7-37 整数分解为若干项之和(20 分) 将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,-.编程求出正整数N的所有整数分解式子. 输入 ...

  6. 分解 python_面试官:如何用Python实现将一个整数分解成质因数?

    概述 今天主要分享一个关于分解质因数的实例,判断的逻辑稍微多了点,一起来看看吧~ 需求 将一个整数分解质因数.例如:输入90,打印出90=233*5 思路 其实根本不需要判断是否是质数,从2开始向数本 ...

  7. 7-37 整数分解为若干项之和 (20 分)(dfs)

    7-37 整数分解为若干项之和 (20 分) 将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,-.编程求出正整数N的所有整数分解式子. 输入格式: ...

  8. 整数分解为若干项之和

    7-37 整数分解为若干项之和 (20 分) 将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,-.编程求出正整数N的所有整数分解式子. 输入格式: ...

  9. 51Nod-1383 整数分解为2的幂【数列】

    1383 整数分解为2的幂  任何正整数都能分解成2的幂,给定整数N,求N的此类划分方法的数量!由于方案数量较大,输出Mod 1000000007的结果. 比如N = 7时,共有6种划分方法. 7=1 ...

最新文章

  1. cnn 反向传播推导_深度学习中的参数梯度推导(三)下篇
  2. LSTM-pytorch 写诗之位置编码
  3. 作为我的第一篇csdn博客吧
  4. FileUpload控件学习
  5. html 表格行排序,用客户端HTML表格排序对行进行分组
  6. [转载] 山楂树之恋——01-03
  7. 使用tar进行磁带备份的命令汇总
  8. git 历史操作日志_git的历史记录
  9. struts的action访问servlet的IOC方式与非IOC方式
  10. vue 插值表达式,v-cloak,v-text,v-html,以及v-bind,v-on
  11. Samba瞎折腾一下
  12. 剖析人生赚钱五大境界颠覆你的认知
  13. vue问题解决 extract:echarts: sill extract echarts@^4.2.0-rc.2 extracted to
  14. android 图片3d旋转动画效果,图片UI特效-3D罗盘旋转
  15. <<飞 鸟 集>> 泰戈尔
  16. 微博相册一键批量下载 Chrome 扩展
  17. 阿里云云计算专业认证考试(ACP级)
  18. SpringBoot实现微信登录
  19. 视频教程-React全栈:前后端分离的招聘Web App项目(含资料)-ReactJS
  20. 我所理解的 restful (关键词:restful)

热门文章

  1. 手把手教你用Scrapy爬取知乎大V粉丝列表
  2. 傍腾讯,切阿里,拼多多的千亿瞒天术
  3. Ubuntu搭建nfs服务器
  4. 我最爱用的一款 Redis 可视化管理工具!好用到爆!!!
  5. 太赞了!刷题PDF终于在GitHub上开源了!覆盖字节、蚂蚁、腾讯等多家大厂真题...
  6. JeecgBoot Minio版本6.0.13升级到8.0.3修改方法
  7. 【插件发布】JAVA微服务框架,Jeecg-P3-Demo 1.0.0 插件开源发布
  8. 微信分享JS-SDK示例页面
  9. SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级
  10. MySQL学习笔记_10_MySQL高级操作(下)