素数相关筛法及素数的性质

1.素数的筛法

    1.1 素数的普通筛

素数的普通筛就是应用一个素数不能分解成除1和其本身的两数相乘,进而进行素数的标记的做法。用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的倍数。依次类推,直到筛子为空时结束。如有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
1不是素数,去掉。剩下的数中2最小,是素数,去掉2的倍数,余下的数是:
3 5 7 9 11 13 15 17 19 21 23 25 27 29
剩下的数中3最小,是素数,去掉3的倍数,如此下去直到所有的数都被筛完,求出的素数为:
2 3 5 7 11 13 17 19 23 29

代码实现如下:

void prime_normal(int n){
	memset(pflag,true,sizeof(pflag));
	pflag[1] = false;
	for (int i = 1; i <= n; ++ i){
		if (!pflag[i]) continue;
		for (int j = 2; j <= n/i ; ++ j){
			pflag[ i * j] = false;
		}
	}
}

然而这种FilterPrime的算法并不是最优O(sqrt(n)log2n)

通过优化可以将其降低至O(n)

 1.2 素数的线性筛(欧拉筛法)

我们考虑减少普通筛中多余的部分(例如当 i = 2, j = 9时会筛去18, 而 i = 3, j = 6时也会筛去18,这就增加了时间复杂度),当这个数第一次被其素因子筛去时,就停止后续的筛(保证每个数只被筛一次)。以达到线性筛的目的。

如此,建立pflag进行标记,用prime数组模拟链接表。

代码如下:

bool pflag[maxn];
int prime[maxn];
tot = 0;
void prime_Euler(int x){
	for (int i = 2; i <= n; ++ i){
		if(!pflag[i]) prime[ ++ tot] = i;
		for (int j = 1; j <= tot && prime[j] * i <= maxn; ++ j){
			pflag[prime[j] * i] = true;
			if ( i % prime[j] == 0) break;
		}
	}
}

*1.1标记素数为true,而1.2标记素数为false(其实就是懒。。)


2.素数的性质

    2.1欧拉函数及证明

   
通式:
 
其中p1, p2……pn为x的所有质因数,x是不为0的整数。

φ(1)=1(唯一和1互质数(小于等于1)就是1本身)。
注意:每种质因数只一个。 比如12=2*2*3那么φ(12)=12*(1-1/2)*(1-1/3)=4
若n是质数p的k次幂,
  
,因为除了p的倍数外,其他数都跟n互质。
设n为正整数,以 φ(n)表示不超过n且与n互素的正整数的个数,称为n的欧拉函数值
φ:N→N,n→φ(n)称为欧拉函数。

性质:

欧拉函数是积性函数——若m,n互质,
 
特殊性质:当n为奇数时,
  ;
若n为质数则
 

证明:

    

设A, B, C是跟m, n, mn互质的数的集,据中国剩余定理,A*B和C可建立一一对应的关系。因此φ(n)的值使用算术基本定理便知,
 
2.2欧拉定理  
数论中,欧拉定理,(也称费马-欧拉定理)是一个关于同余的性质。欧拉定理表明,若n,a为正整数,且n,a互质,则:

证明:

    将1~n中与n互质的数按顺序排布:x1,x2……xφ(n) (显然,共有φ(n)个数)
    我们考虑这么一些数:
    m1=a*x1;m2=a*x2;m3=a*x3……mφ(n)=a*xφ(n)
    1)这些数中的任意两个都不模n同余,因为如果有mS≡mR (mod n) (这里假定mS更大一些),就有:

    mS-mR=a(xS-xR)=qn,即n能整除a(xS-xR)。但是a与n互质,a与n的最大公因子是1,而xS-xR<n,因而左式不可能被n整除。也就是说这些数中的任意两个都不模n同余,φ(n)个数有φ(n)种余数。

    2)这些数除n的余数都与n互质,因为如果余数与n有公因子r,那么a*xi=pn+qr=r(……),a*xi与n不互质,而这是不可能的。那么这些数除n的余数,都在x1,x2,x3……xφ(n)中,因为这是1~n中与n互质的所有数,而余数又小于n.

由1)和2)可知,数m1,m2,m3……mφ(n)(如果将其次序重新排列)必须相应地同余于x1,x2,x3……xφ(n).
故得出:m1*m2*m3……mφ(n)≡x1*x2*x3……xφ(n) (mod n)
或者说a^[φ(n)]*(x1*x2*x3……xφ(n))≡x1*x2*x3……xφ(n)

或者为了方便:K{a^[φ(n)]-1}≡0 ( mod n ) 这里K=x1*x2*x3……xφ(n)。可知K{a^[φ(n)]-1}被n整除。

但K中的因子x1,x2……都与n互质,所以K与n互质。那么a^[φ(n)]-1必须能被n整除,即a^[φ(n)]-1≡0 (mod n),即a^[φ(n)]≡1 (mod n),得证。

    2.3费马小定理

由欧拉定理易证:当a是不能被质数p整除的正整数,则有a^(p-1) ≡ 1 (mod p)    p是任意数

其逆命题不一定成立(但在多数情况下,我们认为这是一个必要条件)


2.4素数判定的基本性质

为了防止上述使用费马小定理的逆否命题的误差,我们采用二次探测法进行优化,

它是根据一个定理:如果p是一个素数,那么对于x(0<x<p),若x^2 mod p 等于1,则x=1或p-1。逆否命题:如果对于x(0<x<p),若x^2 mod p 不等于1,则p不是素数。根据这个定理,我们要计算a^(p-1) mod p是否等于1时,可以这样计算,设p-1=(2^t) * k。我们从a^k开始,不断将其平方直到得到a^(p-1),一旦发现某次平方后mod p等于1了,那么说明符合了二次探测定理的逆否命题使用条件,立即检查x是否等于1或p-1,如果不是则可直接判定p为合数。

Miler - Rabbin 算法(概率算法,但在大多条件下认为是真算法)

以下是模板代码:

bool Miller_Rabbin(int n,int a) { //a 属于[2,n)
	if (n < 2)return false;
	if (!(n%a))return false;
	int r = 0, d = n-1;
	while (!(d&1)) {
		d >>= 1;
		r ++;
	}
	int k = pow_mod( a, d, n);
	if (k == 1)return true;
	for (int i = 0; i < r; ++ i) {
		if (k == n-1)return true;
		k = k * k % n;
	}
	return false;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值