素数

性质

  1. 若 $ x\geqslant 2 $ ,则 $ x= p_1 \times p_2 \times p_3 \times p_4 \times p_5 \times p_6 \times ... \times p_n $

  2. 威尔逊定理: 若 $ p $ 为素数,则 $ (p-1)! \equiv -1 \pmod{p} $ 。 若 $ (p-1)! \equiv -1 \pmod{p} $ 为素数,则 $ p $ 为素数。

  3. 费马定理: 若 $ a,p $ 互质且 $ p $ 为素数, $ a^{p-1} \equiv 1 \pmod{p} $

  4. 费马小定理: 若 $ p $ 为素数, $ a^{p} \equiv a \pmod{p} $

素数的判定

朴素算法

void check(int x)
{
	for(int i=2; i*i<=x; i++)
	{
		if(x%i==0)
		{
			cout<<"NO"<<endl;
			return ;
		}
	}
	if(x==1)cout<<"NO"<<endl;
	else cout<<"YES"<<endl;
}

$ Miller-Rabin $ 素数测试

原理1:费马小定理: 若 $ p $ 为素数, $ a^{p} \equiv a \pmod{p} $

原理2:二向探测定理: 若 \(p\) 为素数并 \(x^2 \equiv 1 \pmod{p}\)\(x=1\)\(x=p-1\)

\(x^2 -1 \equiv 0 \pmod{p}\)
\((x-1)\times (x+1) \equiv 0 \pmod{p}\)
\(x=1\)\(x=p-1\)

  1. 计算 数字 \(m,r\)\(n=2^r + m +1\)

  2. 选择随机数 \(A<n\)\(srand(time(NULL))\) ) ,

  3. 计算 \(A^{2^i + m} (1\le i \le r)\) ,若 \({{A^{2^i + m} \bmod n=1 \quad and \quad (A^{2^{i-1} + m}==1 \quad \mathsf{\text{或}} \quad A^{2^{i-1} + m}==n-1)}}\) 则同过测试,否则 \(n\) 不为素数

4.计算 \({{A^{n-1} \bmod n \quad \mathsf{\text{等于}} \quad A^{2^r + m} \bmod n}}\) , 若值为 \(1\) 则同过测试否则 \(n\) 不为素数.

  1. 重复1至4(大概 \(6,7\) 遍即可).
#define ll unsigned long long
namespace Solve
{
	ll ksc(ll x,ll y,ll mod)
	{
		ll res=0;
		while(y)
		{
			if(y&1)
			{
				res=res+x;
				res%=mod;
			}
			y>>=1;
			x=(x+x)%mod;
		}
		return res;
	}
	ll ksm(ll xx,ll y,ll mod)
	{
		__int128 res=1,x=xx;
		while(y)
		{
			if(y%2==1)res=res*x%mod;
			x=x*x%mod;
			y>>=1;
		}
		return res;
	}
	bool Miller_Rabin(ll n)
	{
		if(n==1)return 0;
		if(n==2)return 1;
		ll m=n-1,r=0;
		while(m%2==0)m>>=1,r++;
		for(ll i=1; i<=10; i++)
		{
			ll a=rand()%(n-1)+1;
			ll x=ksm(a,m,n),nxt;
			for(ll j=1; j<=r; j++)
			{
				nxt=ksc(x,x,n);
				if(nxt==1&&x!=1&&x!=n-1)return 0;
				x=nxt;
			}
			if(x!=1)return 0;
		}
		return 1;
	}
}

提交记录

质数筛

线性算法,可以求出

void find_prime(int n)
{
	int cnt=0;
	for(int i=2; i<=n; i++)
	{
		if(!v[i])
		{
			p[++cnt]=i;
			v[i]=i;
			cout<<i<<" ";
		}
		for(int j=1; p[j]*i<=n&&j<=cnt; j++)
		{
			v[p[j]*i]=p[j];
			if(!(i%p[j]))break;
		}
	}
	cout<<endl;
	for(int i=2; i<=n; i++)cout<<i<<" "<<v[i]<<endl;
	cout<<endl;
}
posted @ 2022-08-04 10:41  fzrcy  阅读(105)  评论(0)    收藏  举报