素数的判断

素数的判断:

素数的判断主要有2种方法:1.试除法 2.Miller_Rabbin随机化算法

一、试除法:

(1)朴素的试除法:

  对于一个数N,我们可以从让其被除遍1~N,如果有一个数可以除尽N,则其为合数,如果都不能将其除尽,则其为质数;

  时间复杂度O(N)

  优化:

    (2)将N从1除到sqrt(N)即可:时间复杂度O(sqrt(N))

     证明:对于任意的N若存在u使得N能被u整除,那么一定存在(N/u),使N可以除尽(N/u);(N/u)*u = N;

        故有方程N/u = u;所以u = sqrt(N);

    (3)将N除从1到sqrt(N)的质数 时间复杂度O(In(sqrt(N))) 当然他有O(N)的筛素数的时间(筛素数的方法见:留坑)

      证明:对于任意一个数N,如果N可以被u除尽,而u是合数,那么他的质因子m一定可以除尽N;

        而根据质数分布规律,在1~N中质数的个数接近于In(N)

        故算法可行,时间复杂度为O(In(sqrt(N))+N)

        如果多次询问(询问m次),时间复杂度为O(mIn(sqrt(N))+N)

        而简单的试除只有O(msqrt(N));

    (4) 玄学数论:如果一个数是质数,那么它取模6只能是1或5。时间复杂度O((1/3)*基础算法复杂度)(2,3特判)

      证明:表示博主也不会证,只是听数竞同学说的,故证明略;

(2)Miller_Rabbin随机化算法:

  原理:如果一个数N,满足a^(N-1) mod N = 1(a为质数),则他极有可能是质数,如果不满足上述性质,则他是合数;

     我们可以取很多个质数,对N进行验证,如果它都符合上述质数的条件,那么我们可以认为他是质数,其正确率经过证明最大接近80%左右;

     错判率还是很大,怎么办?

     于是我们有第二个定理:如果一个数是质数,且N-1是偶数,那么a^((N-1) /2)mod N = 1或N-1;

     我们可以不断的除下去直到判为合数或N-1被除K次后为奇数,经过计算,其正确率为99.9999%;

    时间复杂度O(logN),最坏O((logN)^2)

 

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
long long mul(long long a , long long b , long long P)
{
	long long  tmp = (long double) a * b / P;
  	return ((a * b - tmp * P) % P + P) % P;
}
long long quick_mod(long long a,long long n,long long mod)
{	
	if(n == 0) return 1;
	long long l = quick_mod(a,n/2,mod);
	if(n % 2 == 0) return mul(l,l,mod);
	else return mul(a,mul(l,l,mod),mod);
}
bool Miller_Rabbin(long long x)
{
	if(x == 2 || x == 3) return true;
	if(x % 6 != 5 && x % 6 != 1) return false;
	int prim[9] = {2,3,5,7,11,13,17,19,23};
	long long tmp;
	long long tnp;
	for(int i = 0 ; i < 9 ; i++)
	{
		if(prim[i] == x) return true;
		else if(prim[i] > x) return false;	
		tmp = quick_mod(prim[i],x-1,x);
		tnp = x - 1;
		if(tmp != 1) return false;
		while(tnp % 2 == 0 && tmp == 1) //?
		{
			tnp /= 2;
			tmp = quick_mod(prim[i],tnp,x);
			if(tmp != 1 && tmp != x-1) return false;
		}
	}
	return true;
}

int main(void)
{
	long long int x;
	while(cin>>x)
	{
		if(x == EOF) break;
		else if(x == 1) puts("N");
		else if(Miller_Rabbin(x)) puts("Y");
		else puts("N");
	}
	return 0;
}

  

    

posted @ 2018-11-17 20:25  白萝卜_胡萝卜  阅读(367)  评论(0编辑  收藏  举报
……