Pollard-Rho

Solution

用于拆解较大数的质因子。

前置知识:Miller Rabin

涉及到的思想:

  • 利用 gcd(x,y) 来寻找 x 的因数。

  • 组合随机采样的优秀命中率。

  • gcd(xz,y)=gcd(gcd(x,y)×gcd(z,y),y),因此可以调整步长来判断当前是否找到了因数,减少 gcd 的调用次数。

安利一篇博文,这里面讲得挺详细的,就是有些地方……可能需要你自己理解他真正的意思。


三道板子题

【模板】Pollard-Rho算法

SP4941 FACT1 - Integer Factorization (20 digits)

「数学」约数个数和

确实算是板题,毕竟这个东西就是把数字质因子拆分。

其中第三道题转化完以后就是个 前缀和 的模板。


Code

下面是封装好的,可以直接调用,返回质因数拆分的结果。

测试了 114514,1919810 这两个数的拆分。

namespace Pollard_Rho { inline LL les(LL x,LL y){return x>y?x-y:y-x;} inline LL Gcd(LL x,LL y){return !y?x:Gcd(y,x%y);} inline LL prpr(LL x,LL y,LL p){LL s=(long double)x/p*y+1e-8;s=(ULL)(x*y)-(ULL)(s*p);if(s>=p)s-=p;return s<0?s+p:s;} inline LL ksm(LL x,LL y,LL p){LL ans=1;for(;y;y>>=1){if(y&1)ans=prpr(ans,x,p);x=prpr(x,x,p);}return ans;} bool pri[20]; vector<int>prime; inline void init() { for(int i=2;i<20;i++){if(!pri[i])prime.push_back(i);for(auto j:prime){int now=i*j;if(now>=20)break;pri[now]=true;if(i%j==0)break;}} pri[1]=true;srand(time(0));return; } inline bool Miller_Rabin(LL n,int a) { LL t=n-1,lst;int k=0;for(;!(t&1);t>>=1)k++;lst=t=ksm(a,t,n); for(int i=1;i<=k;i++){t=prpr(t,t,n);if(t==1&&lst!=1&&lst!=n-1)return false;lst=t;}return lst==1; } inline bool ifprime(LL n){if(n<20)return !pri[n];if(n%6!=1&&n%6!=5)return false;for(auto j:prime)if(!Miller_Rabin(n,j))return false;return true;} inline LL f(LL x,int c,LL p){LL nows=prpr(x,x,p)+c;if(nows>=p)nows-=p;return nows;} inline LL Ame(LL n) { LL s,t,c;s=t=0;c=rand()%(n-1)+1; for(int ed=1;;ed<<=1) { LL pro=1;s=t;for(int i=1;i<=ed;i++){t=f(t,c,n),pro=prpr(pro,les(t,s),n);if(i%127==0){LL ans=Gcd(n,pro);if(ans>1)return ans;}} LL ans=Gcd(n,pro);if(ans>1)return ans; } return n; } vector<pair<LL,int> >getpm; inline void Gura(LL n,int cutt) { if(n==1)return;if(ifprime(n)){getpm.push_back(make_pair(n,cutt));return;} LL p=n;for(;p==n;p=Ame(n));int c=0;for(;n%p==0;n/=p)c++;Gura(n,cutt);Gura(p,cutt*c);return; } inline vector<pair<LL,int> > work(LL n) { getpm.clear();Gura(n,1);sort(getpm.begin(),getpm.end());vector<pair<LL,int> >ans;ans.clear(); for(vector<pair<LL,int> >::iterator i=getpm.begin(),j;i!=getpm.end();i=j) { int sum=0;for(j=i;j!=getpm.end()&&j->first==i->first;j++)sum+=j->second; ans.push_back(make_pair(i->first,sum)); } return ans; } } int main() { using namespace Pollard_Rho;init(); vector<pair<LL,int> >a=work(114514);for(vector<pair<LL,int> >::iterator i=a.begin();i!=a.end();i++)printf("%lld^%d ",i->first,i->second);puts(""); vector<pair<LL,int> >b=work(1919810);for(vector<pair<LL,int> >::iterator i=b.begin();i!=b.end();i++)printf("%lld^%d ",i->first,i->second);puts(""); return 0; }

__EOF__

本文作者zjjws
本文链接https://www.cnblogs.com/zjjws/p/14693151.html
关于博主:我就是:究极的 Mad Scientist,凤—凰—院—凶—真da!
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:这么屑的博主有什么声援的必要吗?
posted @   zjjws  阅读(130)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示