• Miller-Rabin


    算法简介

    Miller-Rabin 算法可以较快地判断一个数是不是质数。
    但是,这个算法是概率性算法,即有一定的概率会误判。
    所以,一般会使用较多的数检验,从而降低误判的概率。

    前置定理

    费马小定理(a^{p-1} equiv 1 (mod p))
    注意:费马小定理的逆命题并不一定成立。
    二次探测定理:若 (p) 为奇素数且 (x^2 equiv 1 (mod p)) , 则 (x equiv 1 (mod p))(x equiv p-1 (mod p))

    前置算法

    快速乘,快速幂

    判断过程

    设当前在判断的数是 (x)
    先判掉 (x) 为偶数的情况。
    此时, (x) 为奇数,则 (x-1) 为偶数,
    所以 (x-1) 必然能表示成 (2^q*p)(q)(p) 为正整数) 。
    先在 (1) ~ (n-1) 中随机一个 (a) , 若 (a^{x-1} mod x eq 1) ,根据费马小定理, (x) 为合数。
    因为费马小定理的逆定理并不一定成立,所以现在还并不能判定 (x) 就是质数。
    接下来,枚举一个 (y)(0 leq y leq q-1)
    (a^{2^y*p} mod x=1)(a^{2^{y-1} *p} mod x eq 1)(a^{2^{y-1} *p} mod x eq x-1) ,根据二次探测定理, (x) 为合数。
    若到最后都没有判断 (x) 为合数,则认为 (x) 为质数。
    多用几个 (a) 判断以提高正确率。

    code

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<ctime>
    #define int long long
    #define LD long double
    #define ull unsigned long long
    using namespace std;
    int MUL(int a,int b,int p) //a*b%p
    {
    	int x=(LD)a/p*b;
    	return ((ull)a*b-(ull)x*p+p)%p;
    }
    int POW(int a,int b,int p) //a^b%p
    {
    	if(!b) return 1;
    	if(b==1) return a;
    	int sum=POW(a,b/2,p);
    	if(b%2) return MUL(MUL(sum,sum,p),a,p);
    	return MUL(sum,sum,p);
    }
    bool check(int x)
    {
    	if(x==0||x==1) return false;
    	if(x==2) return true;
    	if(x%2==0) return false;
    	int p=x-1,q=0;
    	while(p%2==0) q++,p/=2;
    	for(int i=1;i<=10;i++)
    	{
    		int a=rand()%(x-1)+1;
    		if(POW(a,x-1,x)!=1) return false;
    		int lst=1;
    		for(int j=0;j<q;j++)
    		{
    			int t=POW(a,(1ll<<j)*p,x);
    			if(t==1&&lst!=1&&lst!=x-1) return false;
    			lst=t;
    		}
    		if(lst!=1&&lst!=x-1) return false;
    	}
    	return true;
    }
    int x;
    signed main()
    {
    	srand(time(0));
    	scanf("%lld",&x);
    	puts(check(x)?"YES":"NO");
    	return 0;
    }
    

    一些提醒

    此算法的时间复杂度为 (O(k log^2 n)) (其中, (k) 为用于判断的质数个数),在数据较大时非常优秀。
    但是,在数据比较小的时候此算法的效率甚至不如 (O(sqrt{n})) 的暴力。所以,在数据小时要慎用。

  • 相关阅读:
    .NET Core中如何对Url进行编码和解码
    How to signout from an Azure Application?(转载)
    2016阿里安全峰会重点资料下载
    只有程序员才看懂的内涵图
    2016乌云白帽资料下载
    Python黑帽编程2.1 Python编程哲学
    Python黑帽编程2.2 数值类型
    Python黑帽编程 2.0 第二章概述
    PYTHON黑帽编程1.5 使用WIRESHARK练习网络协议分析
    乌云挂了,知识库的文章却在流传
  • 原文地址:https://www.cnblogs.com/zhs1/p/14043999.html
Copyright © 2020-2023  润新知