Miller-Rabin素数检测算法
遇到了一个题:
Description:
Goldbach's conjecture is one of the oldest and best-known unsolved problems in number theory and all of mathematics. It states:
Every even integer greater than 2 can be expressed as the sum of two primes.
The actual verification of the Goldbach conjecture shows that even numbers below at least 1e14 can be expressed as a sum of two prime numbers.
Many times, there are more than one way to represent even numbers as two prime numbers.
For example, 18=5+13=7+11, 64=3+61=5+59=11+53=17+47=23+41, etc.
Now this problem is asking you to divide a postive even integer n (2<n<2^63) into two prime numbers.
Although a certain scope of the problem has not been strictly proved the correctness of Goldbach's conjecture, we still hope that you can solve it.
If you find that an even number of Goldbach conjectures are not true, then this question will be wrong, but we would like to congratulate you on solving this math problem that has plagued humanity for hundreds of years.
Input:
The first line of input is a T means the number of the cases.
Next T lines, each line is a postive even integer n (2<n<2^63).
Output:
The output is also T lines, each line is two number we asked for.
T is about 100.
本题答案不唯一,符合要求的答案均正确
样例输入
1
8
样例输出
3 5
题解:预处理1e6范围的素数,暴力这些素数ai 利用素数判定n-ai是否是素数
预处理:线性筛法的模板
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+;
bool check[maxn];
int prime[maxn];
int main(){
int i,j,pos=,flag;
for(i=;i<maxn;i++){
if(!check[i]) prime[pos++]=i;
for(j=;j<pos&&i*prime[j]<maxn;j++){
check[i*prime[j]]=true;
if(i%prime[j]==) break;
}
}
然后就是素数的判断
以下摘录博客:
https://blog.csdn.net/zengaming/article/details/51867240
https://www.cnblogs.com/SinGuLaRiTy2001/p/6591414.html
先说几个理论基础:
1. 费马小定理:假如p是质数,a是整数,且a、p互质,那么a的(p-1)次方除以p的余数恒等于1,即:a^(p-1)≡1(mod p).
但是反过来却不一定成立,就是说,如果a、p互质,且a^(p-1)≡1(mod p),不能推出p是质数,比如Carmichael数。
2. 二次探测定理:如果p是一个素数,0<x<p,则方程x^2≡1(mod p)的解为x=1或x=p-1。
3. 模运算的规则:(a*b)%n=(a%n * b%n)%n
4. 快速积取模、快速幂取模:可以看看我之前写的一篇博客简单快速的算法
这些理论基础还没有好好想过。。
然后是算法的过程:
对于要判断的数n
1.先判断是不是2,是的话就返回true。
2.判断是不是小于2的,或合数,是的话就返回false。
3.令n-1=u*2^t,求出u,t,其中u是奇数。
4.随机取一个a,且1<a<n
/*根据费马小定理,如果a^(n-1)≡1(mod p)那么n就极有可能是素数,如果等式不成立,那肯定不是素数了
因为n-1=u*2^t,所以a^(n-1)=a^(u*2^t)=(a^u)^(2^t)。*/
5.所以我们令x=(a^u)%n
6.然后是t次循环,每次循环都让y=(x*x)%n,x=y,这样t次循环之后x=a^(u*2^t)=a^(n-1)了
7.因为循环的时候y=(x*x)%n,且x肯定是小于n的,正好可以用二次探测定理,
如果(x^2)%n==1,也就是y等于1的时候,假如n是素数,那么x==1||x==n-1,如果x!=1&&x!=n-1,那么n肯定不是素数了,返回false。
8.运行到这里的时候x=a^(n-1),根据费马小定理,x!=1的话,肯定不是素数了,返回false
9.因为Miller-Rabin得到的结果的正确率为 75%,所以要多次循环步骤4~8来提高正确率
10.循环多次之后还没返回,那么n肯定是素数了,返回true
下面是模板:
const ll S = ;
ll mult_mod(ll a, ll b, ll c) {
a %= c;
b %= c;
ll ret = ;
ll tmp = a;
while (b) {
if (b & ) {
ret += tmp;
if (ret > c) ret -= c;
}
tmp <<= ;
if (tmp > c)tmp -= c;
b >>= ;
}
return ret;
}
ll pow_mod(ll a, ll n, ll mod) {
ll ret = ;
ll temp = a % mod;
while (n) {
if (n & )ret = mult_mod(ret, temp, mod);
temp = mult_mod(temp, temp, mod);
n >>= ;
}
return ret;
}
bool check(ll a, ll n, ll x, ll t) {
ll ret = pow_mod(a, x, n);
ll last = ret;
for (ll i = ; i <= t; i++) {
ret = mult_mod(ret, ret, n);
if (ret == && last != && last != n - )return true;
last = ret;
}
if (ret != )return true;
else return false;
}
bool Miller_Rabin(ll n) {
if (n < )return false;
if (n == )return true;
if ((n & ) == )return false;
ll x = n - ;
ll t = ;
while ((x & ) == ) {
x >>= ;
t++;
} srand(time(NULL)); for (ll i = ; i < S; i++) {
ll a = rand() % (n - ) +;
if (check(a, n, x, t))
return false;
}
return true;
}
#include<cstdlib>
#include<ctime>
#include<cstdio>
using namespace std;
const int count=;
int modular_exp(int a,int m,int n)
{
if(m==)
return ;
if(m==)
return (a%n);
long long w=modular_exp(a,m/,n);
w=w*w%n;
if(m&)
w=w*a%n;
return w;
}
bool Miller_Rabin(int n)
{
if(n==)
return true;
for(int i=;i<count;i++)
{
int a=rand()%(n-)+;
if(modular_exp(a,n,n)!=a)
return false;
}
return true;
}
int main()
{
srand(time(NULL));
int n;
scanf("%d",&n);
if(Miller_Rabin(n))
printf("Probably a prime.");
else
printf("A composite.");
printf("\n");
const ll S = ;
ll mult_mod(ll a, ll b, ll c) {
a %= c;
b %= c;
ll ret = ;
ll tmp = a;
while (b) {
if (b & ) {
ret += tmp;
if (ret > c) ret -= c;
}
tmp <<= ;
if (tmp > c)tmp -= c;
b >>= ;
}
return ret;
}
ll pow_mod(ll a, ll n, ll mod) {
ll ret = ;
ll temp = a % mod;
while (n) {
if (n & )ret = mult_mod(ret, temp, mod);
temp = mult_mod(temp, temp, mod);
n >>= ;
}
return ret;
}
bool check(ll a, ll n, ll x, ll t) {
ll ret = pow_mod(a, x, n);
ll last = ret;
for (ll i = ; i <= t; i++) {
ret = mult_mod(ret, ret, n);
if (ret == && last != && last != n - )return true;
last = ret;
}
if (ret != )return true;
else return false;
}
bool Miller_Rabin(ll n) {
if (n < )return false;
if (n == )return true;
if ((n & ) == )return false;
ll x = n - ;
ll t = ;
while ((x & ) == ) {
x >>= ;
t++;
} srand(time(NULL)); for (ll i = ; i < S; i++) {
ll a = rand() % (n - ) +;
if (check(a, n, x,
Miller-Rabin素数检测算法的更多相关文章
- Miller Rabin素数检测与Pollard Rho算法
一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...
- Miller Rabin素数检测
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #inclu ...
- POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】
Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...
- POJ2429_GCD & LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】
GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 ...
- POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】
Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...
- HDU1164_Eddy's research I【Miller Rabin素数测试】【Pollar Rho整数分解】
Eddy's research I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- Miller-Rabin素数检测算法 acm模板
Miller-Rabin素数检测算法 其基于以下两个定理. Fermat小定理 若n是素数,则∀a(a̸≡0(modn))\forall a(a \not\equiv 0 \pmod{n})∀a(a̸ ...
- 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)
关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...
- 【数论基础】素数判定和Miller Rabin算法
判断正整数p是否是素数 方法一 朴素的判定
随机推荐
- SpringCloud学习之Feign 的使用(五)
Feign 是一个声明式的伪RPC的REST客户端,它用了基于接口的注解方式,很方便的客户端配置,刚开始使用时还不习惯,感觉是在客户端写服务端的代码,Spring Cloud 给 Feign 添加了 ...
- UVA 11552 序列划分模型 状态设计DP
这个题目刚看到还真不好下手,把一个是 k的倍数的长度的字符串分成len/k块,每块是k个字母,每个块可以重新组合,最后使得整个序列的相同字母尽量在一起,也就是说,最后会把序列从前往后扫,相连的相同字母 ...
- 在excel中评估模型性能
一直在用的结果, 从代码中整理出来. 评分卡模型的结果一般在excel中即可计算完成. 下面是在number中计算评分卡模型的性能(KS/AUC), 表格中百分数省略%
- Okhttp 多次调用同一个方法出现错误java.net.SocketException: Socket closed
Okhttp 多次调用同一个方法出现错误java.net.SocketException: Socket closed https://blog.csdn.net/QQiqq1314/article/ ...
- Vmware 困惑点记录和解释
个人理解,如果有不同见解,麻烦请留言,一起进行探讨: DRS和HA是两个独立的功能. 准入控制只是保障有资源打开故障后迁移来的虚拟机,就算自身已经超过切换的阈值了,HA也是可以迁移过去的. 虚拟机允许 ...
- try{}catch{}finally{}使用总结
import java.util.Scanner; class MyException extends Exception { public MyException(String Message) { ...
- vue项目开始 首页 part1
stylus 优点:css之中使用一些变量,方便我们快速编写css 项目中我们使用css开发的辅助工具帮助我们开发网站样式 安装:终端打开我们项目的文件夹 npm install stylus --s ...
- Python—使用列表构造队列数据结构
队列的概念 只允许在一端插入数据操作,在另一端进行删除数据操作的特殊线性表:进行插入操作的一端称为队尾(入队列),进行删除操作的一端称为队头(出队列):队列具有先进先出(FIFO)的特性. # _*_ ...
- 每天一杯C_C89、C99、C11等之C语言标准
C语言的伟大之处在于C语言还是一个国际标准,这只“无形的手”掌控者其他派生语言和计算机的各个方面.起关于C语言被发明之后,ANSI和ISO相继发布关于C语言的标准.关于C90和C99,C89和C99容 ...
- 关于gc中对象回收算法的认识
之前学习java时,笔者看到很多学习资料说,gc判断object存活与否的算法是:给对象添加一个引用计数器,每当有一处地方引用它时,计数器值就加1,当引用失效时,计数器值就减1,当对象计数清零时,对象 ...