普通素数 筛法求素数 二次筛法求素数 MillerRabin素数测试【模板】
来源:互联网 发布:时光八音盒 java版 编辑:程序博客网 时间:2024/06/06 11:50
素数和合数共同的性质:
1.a > 1是合数,当且仅当a = b * c,其中1 < b < a,1 < c < a。
2.合数必有素数因子。
3.如果d > 1,p是素数,且d | q,则d = p。
4.设p是素数且p | a*b,则必有p | a或者p | b。
素数的性质:
1.存在无穷多个素数。
2.每个大于1的正整数都有一个素因子。
素数的分布:
素数定理:用π(x)估计小于正整数x的素数有多少个。随着x的增长,π(x) / (x/ln x) = 1。
推论:令pn是第n个素数,其中n是正整数,那么pn ~ n*ln n。
素数的猜想:
1.波特兰猜想:对于任意给定的正整数n,其中n > 1,存在一个素数p,使得n < p < 2*n。
2.孪生素数猜想:存在无穷多的形如p和p+2的素数对。
3.哥德巴赫猜想:每个大于2的正偶数可以写成两个素数的和。可推出任一大于7的奇数都可
写成三个质数之和的猜想。
普通素数判断
int IsPrime(int N) //注意#include<cmath>{ if(N <= 1) return 0; int i; for(i = 2; i <= sqrt(N*1.0); ++i) if(N%i == 0) return 0; return 1;}
筛法求素数[1,N]
const int MAXN = 1000000;bool Prime[MAXN+100]; //Prime[i] == true表示i为素数void IsPrime(){ for(int i = 2; i <= MAXN; ++i) Prime[i] = true; for(int i = 2; i <= MAXN; ++i) if(Prime[i]) for(int j = i+i; j <= MAXN; j+=i) Prime[j] = false;}
二次筛法求素数[L,R]
bool Prime[50010]; //存50000内素数判断结果int Primer[1000010]; //存放区间[L,R]之间的素数bool Prime1[1000010]; //判断区间[L,R]中的数是否为素数int IsPrime()//第一次筛50000内的素数{ int num = 0; for(int i = 2; i <= 50000; i++) Prime[i] = true; for(int i = 2; i <= 50000; i++) { if(Prime[i]) { Primer[num++] = i; for(int j = i+i; j <= 50000; j+=i) Prime[j] = false; } } return num; //num为50000范围内的素数个数}int IsPrime2(__int64 a,__int64 b)/*在第一次筛素数的基础上,利用50000以内的素数,筛去范围【a,b】之间的素数倍数,剩下则为素数*/{ int num = IsPrime(); memset(Prime1,true,sizeof(Prime1)); //Prime1数组用来存放范围【a,b】的素性判断 if(a == 1) //这里注意1不是素数 Prime1[0] = 0; //这里表示0+1不为素数 for(__int64 i = 0; i < num && Primer[i] * Primer[i] <= b; i++) { __int64 begin = a/Primer[i] + (a%Primer[i] != 0); //上边的a/Primer算出应a为素数Primer[i]的多少倍 //(a%Primer[i]!=0)表示应从Primer[i]的a/Primer[i]倍开始筛,还是a/Primer[i]+1倍筛 if(begin == 1)//若得出结果为所被筛素数的1倍,则从该素数的2倍开始筛 begin++; for(begin = begin*Primer[i]; begin <= b; begin += Primer[i]) Prime1[begin - a] = false; } //这里重新利用Primer数组,用来存放区间【a,b】间的素数,num为素数个数 memset(Primer,0,sizeof(Primer)); num = 0; for(__int64 i = a; i <= b; i++) if(Prime1[i-a]==1) Primer[num++] = i-a; return num; //num为区间[a,b]的素数个数}
Miller素数测试方法
#include<stdio.h>#include<stdlib.h>#include<time.h>#include<math.h>#define MAX_VAL (pow(2.0,60))#define LL __int64/*LL mod_mul(LL x,LL y,LL mo) //计算x * y % mo{ LL t; x %= mo; for(t = 0; y; x = (x<<1)%mo,y>>=1) if(y & 1) t = (t+x) %mo; return t;}*/LL mod_mul(LL x,LL y,LL mo) //计算x * y % mo{ LL t,T,a,b,c,d,e,f,g,h,v,ans; T = (LL)(sqrt(double(mo)+0.5)); t = T*T - mo; a = x / T; b = x % T; c = y / T; d = y % T; e = a*c / T; f = a*c % T; v = ((a*d+b*c)%mo + e*t) % mo; g = v / T; h = v % T; ans = (((f+g)*t%mo + b*d)% mo + h*T)%mo; while(ans < 0) ans += mo; return ans;}LL mod_exp(LL num,LL t,LL mo) //计算num^t % mo{ LL ret = 1, temp = num % mo; for(; t; t >>=1,temp=mod_mul(temp,temp,mo)) if(t & 1) ret = mod_mul(ret,temp,mo); return ret;}bool miller_rabbin(LL n) //miller_rabbin素性测试{ if(n == 2) return true; if(n < 2 || !(n&1)) return false; int t = 0; LL a,x,y,u = n-1; while((u & 1) == 0) { t++; u >>= 1; } for(int i = 0; i < 50; i++) { a = rand() % (n-1)+1; x = mod_exp(a,u,n); for(int j = 0; j < t; j++) { y = mod_mul(x,x,n); if(y == 1 && x != 1 && x != n-1) return false; x = y; } if(x != 1) return false; } return true;}
0 0
- 普通素数 筛法求素数 二次筛法求素数 MillerRabin素数测试【模板】
- MillerRabin 素数测试【摘自旧博】
- 【个人模板】 筛法求素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- 素数
- NP问题和计算复杂度
- maven笔记
- 黑马程序员_Java中的递归学习(二)
- 查表及表注释
- greenDAO讲义(二):数据库查询篇
- 普通素数 筛法求素数 二次筛法求素数 MillerRabin素数测试【模板】
- 惊群现象
- spring框架_01
- python字符串/元组/列表/字典互转
- iOS8 沙盒路径变化特性
- NOJ 机器狗组装费用 (优先权队列)
- Gradle: error code 42 Unable to open PNG file
- cv::absdiff函数的用法
- 将Centos的yum源为国内的阿里云源