Pollard-Rho算法学习笔记

\(Pollard-Rho\)算法学习笔记

我愿称之为\(RP\)算法

算是咕咕咕了很久的一个知识点,今天补一补(主要是\(T2\)考了就很寄)

好像我昨天跳到了这个题时候说\(:\)这个东西谁也不会考吧。今天就开幕雷击了

首先是\(Miller-Rabin\)判断素性

一个玄学(基于随机的算法),莫名很喜欢这个算法。。。

常用的判断素性方法,\(O(\sqrt n)\)暴力枚举,\(n<=10^{18}\)完美\(TLE\)

基础数论里面的费马小定理

\(a^{\phi(p)-1}=1(\mod p)\)\((1<=a<p)\)

逆否命题成立,假如存在\((1<=a<p)a^{p-1}\neq 1\),那么\(p\)不为质数

我们可以随机选择数字,快速幂判断素性

但是即使满足了所有\((1<=a<p)a^{p-1}=1(\mod p),\)这个数也不一定是质数

那么就需要进行二次检验

若满足\(x^2=1(\mod p)\)的解为\(x=±1(\mod p)\)

具体流程\(:\)

\(p\)是奇数,那么\(p-1\)是偶数,随机选取底数\(a\)

\(a^{p-1}=1\),然后\(d=\frac{(p-1)}{2}\),相当于对\(a\)开根号继续判断

最后是奇数时候只需判断是否\(a^d\neq ±1(\mod p)\),相当于求解上一步的根就好了

那么关于\(Pollard-Rho\)算法

基本过程\(:\)

随机数,两两做差,判断是否成环,之后判断即可

#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define int long long
using namespace std;
mt19937_64 rd(random_device{}());
int T,in;
int MO(int x,int mod)
{
    if(x<mod) return x;
    return x-mod;
}

int my_pow(int a,int b,int mod)
{
    int res=1;
	while(b)
	{
	      if(b&1)
		  {
	         res=((__int128_t)res*a)%mod;
		  }	 
          a=(__int128_t)a*a%mod;
          b>>=1;
	}
	return res;
}
bool test(int x,int r,int t,int mod)
{
	 x=my_pow(x,r,mod);
	 if(x==1||x==mod-1) return false;
	 for(int i=1;i<t;i++)
	 {
	 	 x=(__int128_t)x*x%mod;
	 	 if(x==mod-1) return false;
	 }
	 return true;
}
bool mlrb(int x)
{
	 if(x<2) return false;
	 int t=0,r=(x-1);
	 while(r%2==0) r>>=1,t++;
	 for(int i:{2,3,5,7,11,13,17,19,23,29,31,37})
	 {
	 	 if(x==i) return true;
	 	 if(test(i,r,t,x)) return false;
	 }
	 return true;
}
int gcd(int a,int b)
{
	if(!a) return b;
	if(!b) return a;
    int t=__builtin_ctzll(a|b);
	a>>=__builtin_ctzll(a);
    do
	{
        b>>=__builtin_ctzll(b);
        if(a>b){long long t=b;b=a,a=t;}
        b-=a;
    }
	while(b);
    return a<<t;
}
int Getp(int x)
{
	if(x==1) return x;
	if(x&1^1) return 2;
	int a=(uniform_int_distribution<long long>(2,x-1))(rd),b=a;
	int c=(uniform_int_distribution<long long>(1,x-1))(rd),d=1;
    while(d==1)
    {
    	  a=MO((int)((__int128_t)a*a%x)+c,x);
    	  b=MO((int)((__int128_t)b*b%x)+c,x);
    	  b=MO((int)((__int128_t)b*b%x)+c,x);
          d=gcd(abs(a-b),x);
          if(d==x) return Getp(x);
	}
	return d;
}
vector<int> Getys(int x)
{
	  vector<int>ys;
	  queue<int>q;
	  q.push(x);
	  while(!q.empty())
	  {
	  	     int now=q.front();
	  	     q.pop();
	  	     if(mlrb(now)) ys.push_back(now);
	  	     else
	  	     {
	  	         int y=Getp(now);
	  	         q.push(y);
	  	         q.push(now/y);
			 }
	  }
	  return ys;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
	{
		  scanf("%lld",&in);
		  vector<int>ys=Getys(in);
		  if(ys.size()==1) puts("Prime");
		  else
		  {
		  	  int Max=0;
		  	  sort(ys.begin(),ys.end());
		  	  cout<<ys[ys.size()-1]<<"\n";
		  }
	}
}
posted @ 2022-04-04 20:28  Authentic_k  阅读(35)  评论(0编辑  收藏  举报