素数
素数可以说是组成一个数的基本单位,关于素数的算法有线性筛素数,唯一分解定理与素数快速判断,这里来介绍一下线性筛素数的算法。
线性筛素数
void prim()
{
bool su[MAXN];
int sn[MAXN],num,n,t;
su[0]=1;su[1]=1;
for(int i=2;i<=n;i++)
{
if(!su[i]) sn[++num]=i;
for(int j=1;sn[j]*i<=n&&j<=num;j++)
{
su[i*sn[j]]=1;
if(!(i%sn[j])) break;
}
}
}
这个算法可以说”几乎”是的O(n)的,虽然程序看上去并不是。
这个算法保证了每个合数只被筛了一次。
因为这种算法保证每一个合数由其最小的素数和一个最大的合数筛去的。
if(!(i%sn[j]))break;
我们可以这样理解。i=p(a的最小质因子)*a(一个合数)。
如果i%sn[j]==0,那么p*a*sn[k+1] 可以被后面的a*prime[k+1]再与p筛出来。
因为p < sn[j+1], 所以再这时应该停止。
素数快速判断 Miller-Rabin算法
Miller-Rabin算法随机生成底数a,进行多次调用函数进行测试,Miller-Rabin检测也存在伪素数的问题,但是与费马检测不同,MR检测的正确概率不依赖被检测数p,而仅依赖于检测次数。已经证明,如果一个数p为合数,那么Miller-Rabin检测的证据数量不少于比其小的正整数的3/4,换言之,k次检测后得到错误结果的概率为(1/4)^k。我们在实际应用中一般可以测试15~20次。