第一章 数论(基础知识 1.8)

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互质,则:{\color{Red} a^{p-1}\equiv 1(mod p)} 。( {\color{Red} a^{p}\equiv a(modp)} )

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,则方程{\color{Red} x*x\equiv 1(mod p)}的解为x=1,x=p-1。

证明:由上式,x*x-1\equiv 0(modp)  , 即(x-1)*(x+1)\equiv 0(modp).

因为p是素数,所以p|(x-1)||p|(x+1),又因为0<x<p,所以x=1或x=p-1。

我们可以在利用费马小定理计算a^{n}modn的过程中,增加对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欧拉定理

费马定理式用来阐述素数模下,指数同余的性质,当模是合数时就要用欧拉定理了。

欧拉函数:

欧拉函数又称为\phi函数,对于正整数n,欧拉函数是小于等于n的数中与n互质的数的数目。

欧拉定理:

若a与m互质,则a^{\phi (m)}\equiv 1(modm) 。

1.8.5Pallard Rho 算法求大数因子

大整数分解

参考博客https://www.cnblogs.com/fzl194/p/9047710.html

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值