分解质因数


原理部分

由于时间限制,后续会补充学习

代码实现

PollardRho( 时间复杂度 $O(\frac{n}{4})$ )

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<ctime>
typedef long long ll;
typedef unsigned long long ull;
typedef long double lb;
using namespace std;
int n;
ll ans,m;
//ll cnt[100000],num;用于记录质因子 
inline ll Abs(ll x)
{
	return x<0?-x:x;
}
inline ll gcd(ll a,ll b)
{
	ll c;
	while(b)
	{
		c=a;
		a=b;
		b=c%b;
	}
	return a;
}
inline ll ksc(ull x,ull y,ll p) //O(1)快速乘(防爆long long)
{
	return (x*y-(ull)((lb)x/p*y)*p+p)%p;
}
inline long long ksm(long long a, long long k, long long p)   // a 底数, k 指数, 求 a^k mod p
{
	long long res = 1;
	a%=p;
	while(k > 0)
	{
		if (k & 1) res =ksc(res,a,p);
		a = ksc(a,a,p);
		k >>= 1;
	}
	return res;
}
inline bool mr(ll x,ll p) //mille rabin判质数
{
	if(ksm(x,p-1,p)!=1) return 0;//费马小定理
	ll y=p-1,z;
	while(!(y&1)) //二次探测
	{
		y>>=1;
		z=ksm(x,y,p);
		if(z!=1&&z!=p-1)return 0;
		if(z==p-1)return 1;
	}
	return 1;
}
inline bool prime(ll x)//用于判断是否为质数
{
	if(x<2)return 0;//mille rabin判质数
	if(x==2||x==3||x==5||x==7||x==43) return 1;
	return mr(2,x)&&mr(3,x)&&mr(5,x)&&mr(7,x)&&mr(43,x);
}

inline ll rho(ll p) //求出p的非平凡因子
{
	ll x,y,z,c,g;
	int i,j;//先摆出来(z用来存(y-x)的乘积)
	while(1) //保证一定求出一个因子来
	{
		y=x=rand()%p;//随机初始化
		z=1;
		c=rand()%p;//初始化
		i=0,j=1;//倍增初始化
		while(++i) //开始玄学生成
		{
			x=(ksc(x,x,p)+c)%p;//可能要用快速乘
			z=ksc(z,Abs(y-x),p);//我们将每一次的(y-x)都累乘起来
			if(x==y||!z)break;//如果跑完了环就再换一组试试(注意当z=0时,继续下去是没意义的)
			if(!(i%127)||i==j) //我们不仅在等127次之后gcd我们还会倍增的来gcd
			{
				g=gcd(z,p);
				if(g>1)return g;
				if(i==j)y=x,j<<=1;//维护倍增正确性,并判环(一箭双雕)
			}
		}
	}
}

inline void prho(ll p) //不断的找他的质因子,如果要记录质因子在此处添加
{
	if(p<=ans)return ;//最优性剪纸
	if(prime(p))
	{
		ans=p;
		//cnt[++num]=p;记录质因子 
		return;
	}
	ll pi=rho(p);//我们一次必定能求的出一个因子,所以不用while
	while(p%pi==0)p/=pi;//记得要除尽
	return prho(pi),prho(p);//分开继续分解质因数
}
int main()
{
//	freopen("in.txt","r",stdin);
	cin>>n;
	srand(time(0));//随机数生成必备!!!
	for(int i=1; i<=n; ++i)
	{
		ans=1;
		cin>>m;
		prho(m);
		if(ans==m) cout<<"Prime"<<endl;
		else cout<<ans<<endl;
	}
	return 0;
}

应用场景

1.大数因子求解


如果本文帮助到了你,帮我点个广告可以咩(o′┏▽┓`o)


评论
  目录