1.8 素数
1.8.1素数的判定
(1)数据范围较小的情况下,穷举法判断素数:
int prime(int x)
{
if(x==1||x==0)return 0;
if(x==2)return 1;
for(int i=2;i<=sqrt(x);i++)
if(x%i==0)return 0;
return 1;
}
(2)数据范围比较大,且需要找出所有素数,用筛选法求素数:
void make_prime()
{
memset(is_prime,1,sizeof(is_prime));
is_prime[0]=false;
is_prime[1]=false;
int N=31700,cnt=0;
for(int i=2;i<N;i++)
{
if(is_prime[i])
{
prime[++cnt]=i;//存储
//筛除
for(int j=i*i;j<N;j+=i)
is_prime[j]=false;
}
}
}
(3)筛选法求素数会造成重复筛选合数,影响效率,比如:30,在i=2的时候,j=2*15筛选了一次,在i=5的时候,j=5*6又筛选了一次。而快速线性筛选法没有冗余,不会重复筛选一个数。
long long int prime[N]={0},num_prime=0;
int is_notprime[N]={1,1};
void main()
{
for(int i=2;i<N;i++)
{
if(!is_notprime[i])prime[num_prime++]=i;
for(int j=0;j<num_prime&&i*prime[j]<N;j++)//两种情况:i是素数和i是合数
{
is_notprime[i*prime[j]]=1;
//当i是素数,筛除的是当前求得的最大素数与已经求得的素数的乘积。不会造成重复
if(!i%prime[j])break;
//当i时合数,只能筛除i与i分解式中最小素数的乘积,也不会造成重复
//且所有合数都能被筛除
}
}
return 0;
}
参考链接https://www.jianshu.com/p/f16d318efe9b
1.8.2素数的相关定理
数学一本通P35
唯一分解定理
威尔逊定理(证明https://blog.csdn.net/sssogs/article/details/8641860)
费马小定理:若p为素数,a为正整数,且p和a互质,则: 。(
)
1.8.3Miller-Rabin 素数测试
Miller-Rabin素性检验是一种素数判定法则,因测试计算速度快被广泛应用。它利用随机化算法,判断一个大整数n是否为素数。在Miller-Rabin算法中,被判定不是素数的n一定不是素数,但被判定是素数的只能说是以高概率判定可能为素数。
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
const int count_=10;
int modular_exp(int a,int m,int n)//计算a^m mod n
{
if(m==0)return 1;
if(m==1)return a%n;
long long w=modular_exp(a,m/2,n);
w=w*w%n;
if(m&1)w=w*a%n;
return w;
}
bool Miller_Rabin(int n)
{
if(n==2)return true;
if(n<2||!(n&1))return false;
for(int i=0;i<count_;i++)
{
int a=rand()%(n-2)+2;//保证a为<n的随机数
if(modular_exp(a,n,n)!=a)return false;//费马小定理
}
return true;
}
int main()
{
srand(time(NULL));
int n;
cin>>n;
if(Miller_Rabin(n))cout<<"Probably a prime."<<endl;
else cout<<"A composite."<<endl;
}
Miller-Rabin算法的依据是费马小定理,但费马小定理只是素数判定的一个必要条件。(即满足费马小定理的n未必都是素数,有的合数也满足,但数量极少,这些合数被称为Carmichael数,前三个Carmichael数为561,1105,1729.Carmichael数是非常少的,在1~100000000范围内的整数中只有255个Carmichael.)
利用下面的二次探测定理,可以对上面的素数判定算法做进一步改进,以避免将Carmichael数当作素数。
二次探测定理:
如果p是一个素数,且0<x<p,则方程的解为x=1,x=p-1。
证明:由上式, , 即
.
因为p是素数,所以p|(x-1)||p|(x+1),又因为0<x<p,所以x=1或x=p-1。
我们可以在利用费马小定理计算的过程中,增加对n的二次检测,如果不满足,即可得出n不是素数的结论。
int runFermatPower(int a, int b, int n)// a^b mod n
{
int result = 1;
while (b > 0) {
if ((b & 1) == 1)
result = (result * a) % n;
if ((a * a) % n == 1 && a != 1 && a != n - 1)
return -1;// 二次探测
b >>= 1;
a = (a * a) % n;
}
return result;
}
还不太懂为啥x代入为a,先放在这吧~~
1.8.4欧拉定理
费马定理式用来阐述素数模下,指数同余的性质,当模是合数时就要用欧拉定理了。
欧拉函数:
欧拉函数又称为函数,对于正整数n,欧拉函数是小于等于n的数中与n互质的数的数目。
欧拉定理:
若a与m互质,则 。
1.8.5Pallard Rho 算法求大数因子
大整数分解
参考博客https://www.cnblogs.com/fzl194/p/9047710.html