首页 > 其他分享 >质数判断&质因数分解

质数判断&质因数分解

时间:2024-01-18 22:55:07浏览次数:36  
标签:判断 return 因数分解 ll sq pollard rho 质数

引入

众所周知,素数的判断在 long long 级别是不能 \(O(\sqrt{n})\) 硬上的。那怎么办呢??

参考文献

ababab,先来最低效的。

以下复杂度均考虑高精。

1.试除法

\(O(\sqrt n)\) 枚举,\(n\le 10^{14}\)。

优化

只枚举质数,无法优化预处理质数时间。

2.Millar-Rabin

long long:\(O(k\times(\log n)^3)\),检验 \(k\) 次,正确率至少 \(1-4^{-k}\)。

极大值域:若广义 Riemann 猜想(GRH)成立,\(O((\log n)^5)\)。

原理

\(x^2\equiv 1(mod\hspace{0.2cm}p)\) 的解有且仅有 \(\pm1\)。

加强(Fermat小定理)

\(x^{p-1}\equiv 1(mod\hspace{0.2cm}p),x\in[2,p-1]\)

同时满足以上两个的很大可能是质数

考虑随机 \(x\) 验证,注意到任何合数一定会有底数不通过(至少 \(75\%\))。(如果仅仅是 Fermat 小定理有 Carmichael 数的存在)。

通过前人的努力,int 范围内仅需取 \(\{2, 7, 61\}\),long long 范围内仅需取 \(\{2, 325, 9375, 28178, 450775, 9780504, 1795265022\}\) 或 \(\{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37\}\)(前 \(12\) 个质数)。

优美的实现

同时实现了以上两种判断(好优雅~~)。要写 mul 函数。

const ll bpr[]={};
inline bool miller_rabin(ll p){
	if((~p&1)||p<3) return p==2;
	ll k=__builtin_ctzll(p-1),mod=p;
	--p;p>>=k;
	for(int i=0;i<7;++i){
		ll a=ksm(bpr[i]%mod,p,mod);
		if(a==1||!a) continue;
		int j;
		for(j=1;j<=k;++j){
			if(a==mod-1) break;
			a=mul(a,a,mod);
		}
		if(j>k) return 0;
	}
	return 1;
}

3.Lucas序列

咕。

4.n-1法

  • 定理1

若存在 \(ord_n(a)=n-1\),则 \(n\) 为质数。

  • 定理2

若 \(n-1=FR\),已知 \(F\) 的所有质因子 \(q\),且有:

\[\begin{cases} a^{n-1}\equiv1(mod\hspace{0.3cm}n)\\ \gcd(a^{(n-1)/q}-1,n)=1 \end{cases} \]

若 \(F>n^{\frac{1}{4}+\epsilon}\),则 \(n\) 为质数。

只有已知 \(q\) 才行!

n+1 法

咕。

剩下的不管了。


质因数分解(Pollard-Rho)

基本思想

随机出 \(n\) 的一个非平凡因数(\(\in[2,n-1]\)),递归处理。

优化以下,设计一个能取到所有值的不那么随机的随机函数 \(f(x)=(x^2+c)\%n\)

它的图像是 \(\rho\) 型。

根据生日悖论,这里数量小于 \(minp^{\frac{1}{2}}\) 即 \(n^{\frac{1}{4}}\)。

若 \(x_i\equiv x_j\),则 \(f(x_i)\equiv f(x_j)\)。

即 \(x_{i+k}\equiv x_{j+k}\)。

只要枚举所有 \(k\) 就好了。

这里很简略,代码更草率。

码1,定点前跳

vector<ll>pr;
inline void pollard_rho(ll n){
	if(n==1) return ;
	if(miller_rabin(n)) return (void)pr.push_back(n);
	ll sq=sqrt(n);
	if(sq*sq==n) return (void)pollard_rho(sq),pollard_rho(sq);
	ll x0=mr()%(n-1)+1,x1=x0,c=mr()%(n-1)+1,d=1,td;
	for(int T=1;d==1||d==n;T<<=1){
		if(!T) x0=mr()%(n-1)+1,x1=x0,c=mr()%(n-1)+1,T=1;
		d=1;
		x1=x0;
		for(int i=1;i<=T;++i){
			x0=ne(x0,c,n);
			if(x0==x1){
				T=0;
				break;
			}
			td=mul(d,abs(x1-x0),n);
			if(td) d=td;
			if(!(i&127)){
				d=gcd(n,d);
				if(d>1) break;
			}
		}
		d=gcd(n,d);
	}
	pollard_rho(d),pollard_rho(n/d);
}

码2,快慢指针

vector<ll>pr;
inline void pollard_rho(ll n){
	if(n==1) return ;
	if(miller_rabin(n)) return (void)pr.push_back(n);
	ll sq=sqrt(n);
	if(sq*sq==n) return (void)pollard_rho(sq),pollard_rho(sq);
	ll x0=mr()%(n-1)+1,x1=x0,c=mr()%(n-1)+1,d=1,td;
	for(int T=1;d==1||d==n;T<<=1){
		if(!T) x0=mr()%(n-1)+1,x1=x0,c=mr()%(n-1)+1,T=1;
		d=1;
		x1=x0;
		for(int i=1;i<=T;++i){
			x0=ne(x0,c,n),x1=ne(ne(x1,c,n),c,n);
			if(x0==x1){
				T=0;
				break;
			}
			td=mul(d,abs(x1-x0),n);
			if(td) d=td;
			if(!(i&127)){
				d=gcd(n,d);
				if(d>1) break;
			}
		}
		d=gcd(n,d);
	}
	pollard_rho(d),pollard_rho(n/d);
}

细节

  • 优化 \(\gcd\),分块+倍增乘起来搞。

  • 特判平方数(仅仅加速)。

  • Miller-Rabin 特判 n<=3||n%2==0

标签:判断,return,因数分解,ll,sq,pollard,rho,质数
From: https://www.cnblogs.com/mRXxy0o0/p/17973604

相关文章

  • winform Application.OpenForms 判断打开的窗体数量
    List<string>openFrom=newList<string>();if(Application.OpenForms.Count>2){stringresult=string.Empty;for(inti=0;i<Application.OpenForms.Count;i++){......
  • JavaScript(JS) 判断没有属性的空对象{}的四种方法
    ​ JavaScript(JS)中对象没有属性初始化时,可能使用{}进行初始化,如此我们判断这样的没有属性的空对象就不是很方便,本文主要介绍JavaScript(JS)中判断没有属性的空对象{}的五种方法,以及相关的示例代码。1、通过JSON.stringify()判断可以使用JSON.stringify()将Javascript对象......
  • 为啥替换后int类的数据直接NaN了,加了判断也是没替换成功?
    大家好,我是皮皮。一、前言前几天在Python最强王者交流群【哎呦喂 是豆子~】问了一个Pandas数据处理问题,一起来看看吧。问题描述:大佬们这个是为啥呀啊? 为啥替换后int类的数据直接NaN了 加加了判断也是没替换成功原始数据如下:tt=pd.DataFrame({'name':['A','B','C'],......
  • c# 求质数的方法
    质数定义法:质数是指只能被1和自身整除的正整数,即除了1和它本身以外没有其他因数。因此,判断一个数是否为质数,只需要将它分别除以2到它的平方根的整数,如果都不能整除,则它就是质数。这种方法比较简单直观,但对于较大的数会比较耗时。1staticboolIsPrime(intnum)2......
  • vba 判断单元格是否为空
    SubsetBlankRowColor()DimlngLastRowAsLongDimiAsLong'获取工作表中已使用区域最后一行的行号lngLastRow=Cells(Rows.Count,1).End(xlUp).Row'遍历行Fori=1TolngLastRow'判断每行中第1列的单元格是否为空I......
  • java代码里如何判断某个IP/域名是否可达?
    在Java中,你可以使用java.net.InetAddress类来实现ping某个IP地址是否可达。下面是一个简单的示例代码:importjava.net.InetAddress;importjava.io.IOException;publicclassPingExample{publicstaticvoidmain(String[]args){StringipAddress="你的......
  • 判断一个点是否在一个范围中
    这个方法可以加入到工具类中去使用.注意:在使用此方法在判断经纬度时,一定要与使用地图一样的经纬度.附上:https://api.map.baidu.com/lbsapi/getpoint/index.html百度地图的拾取坐标系统/***返回一个点是否在一个多边形区域内*@parammPoints多边形坐标点列表......
  • sql server 判断是否存在数据库,表,列,视图
    1判断数据库是否存在ifexists(select*fromsys.databaseswherename='数据库名')    dropdatabase[数据库名]2判断表是否存在ifexists(select*fromsysobjectswhereid=object_id(N'[表名]')andOBJECTPROPERTY(id,N'IsUserTable')=1)    droptabl......
  • C# socket tcp/ip 如何判断连接是否正常
    判断socket是否断开连接,网上有N种说法:1.Socket.Connected这个属性只能说明上一次通信时还是正常的。比如说你拔掉网线后就它显示还是为true。用这个方法最好和ping一起组合使用。ping的方法如下publicboolPingOC(Stringips){boolret;Processp=newProcess();p.Start......
  • 使用Optional更优雅地处理非空判断
    (一)引言在平常的编码之中,有一个错误总会在你的意料之外出现,那就是空指针异常。空指针的出现也很简单,你得到了一个null对象,调用了一些方法,出现空指针异常。空指针会出现在各种地方,常见的比如Map.get()没有获取到对象就调用对象例的方法,类对象没有获取到就调用类中的方法。空指针......