28.1 朴素的素数判别
bool isPrime(__long n)
{
//简单的判断素数的确定性算法
__long i;
if(n == 2|| n == 3)
return true;
if(n % 2 ==0)
return false;
for(i = 3;i < (__long)sqrt((double)n) + 1; i += 2){
if(n %i == 0)
returnfalse;
}
return true;
}
int prime(int n)
{
int i;
for(i=2;i*i<=n;i++)
if(n%i==0)
return0;
return1;
}
28.2 素数筛选
void Prime() {
memset(a, 0, n*sizeof(a[0]));
int num =0, i, j;
for(i = 2;i < n; ++i) {
if(!(a[i]))
{
p[num++] = i;
}
for(j =0; (j<num && i*p[j]<n); j++){
a[i*p[j]] = 1;
if(!(i%p[j]))
{
break;
}
}
}
}
28.3 Miller-Rabin随机性素数测试方法
28.3.1 实例
PKU JudgeOnline, 1811, Prime Test.
28.3.2 问题描述
判断一个数N (2 < N < 254)是不是素数,是素数就输出 “Prim”,否则输出其最小的因子。
28.3.3 分析
这个题目考察的问题相当多,可以分为大素数的判别法、大数的分解两个问题。其中又牵涉到最大公约数的辗转相除求法(欧几里德算法)、模运算的性质(方幂模、模乘的实现)等。
这里N选取的范围恰到好处。输入的数不是很大,故此可以用__int64类型进行加、减、除、模运算。但是又要注意不能进行乘法运算,否则会溢出。
使用朴素的素数判别显然是不行的。这里需要使用概率算法:Miller-Rabin算法。其中Miller-Rabin需要求积的模和求乘方的模,这些都可以根据模的性质分解,使得计算不会溢出。
在完成素数判别之后,需要采用Pollard的rho启发式随机算法进行素数分解。该算法可能造成死循环。虽然死循环的可能性并不大,不幸碰到了就多提交几次。</