素数及其性质

素数又称质数。指整数在一个大于 111 的自然数中,除了 111 和此整数自身外,没法被其他自然数整除的数。

性质1 有无穷多个素数。

证明: 用反证法。设已知的最大素数为 PPP,考虑S=2×3×5×…×P+1S=2\times3\times5\times…\times P+1S=2×3×5×…×P+1

显然所有已知素数都无法整除 SSS,所以我们找到了一个更大的素数。Q.E.D..\text{Q.E.D..}Q.E.D..

性质2 对于正整数 p,qp,qp,q,若 ppp 是素数且 p∤qp\nmid qp∤q,则 p,qp,qp,q 互素。

证明: 由素数定义知, ppp 的因子为 1,p1,p1,p。

∵p∤q,\because p\nmid q,∵p∤q,

∴gcd⁡(p,q)=1,\therefore \gcd(p,q)=1,∴gcd(p,q)=1,

即 p,qp,qp,q 互素。Q.E.D..\text{Q.E.D..}Q.E.D..

性质3 对于任意正整数 NNN,存在连续的 NNN 个合数。

证明: 考虑

(N+1)!+2,(N+1)!+3,(N+1)!+4,...,(N+1)!+N(N+1)!+2,(N+1)!+3,(N+1)!+4,...,(N+1)!+N(N+1)!+2,(N+1)!+3,(N+1)!+4,...,(N+1)!+N

这 NNN 个数都是合数。Q.E.D..\text{Q.E.D..}Q.E.D..

性质4 若 ppp 是素数,aaa 是小于 ppp 的正整数,则 apmod  p=1a^p\mod p= 1apmodp=1。

证明: 详细证明戳这里

题目描述 loj10197\text{loj10197}loj10197

给定两个整数 L,RL,RL,R,求闭区间 [L,R][L,R][L,R] 中相邻两个质数差值最小的数对与差值最大的数对。当存在多个时,输出靠前的素数对。

输入格式

多组数据。每行两个数 L,RL,RL,R。

输出格式

详见输出样例。

样例输入

2 17
14 17

样例输出

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.

数据范围与提示

对于全部数据,1≤L≤R≤2311≤L≤R≤2^{31}1≤L≤R≤231,R−L≤106R-L≤10^6R−L≤106。

Solution 10197\text{Solution 10197}Solution 10197

由于 R−LR-LR−L 的数值较小,自然想到把 [L,R][L,R][L,R] 间的素数筛出,然后找出答案。

对于 [L,R][L,R][L,R] 区间的数的质因子集 {S}\{S\}{S},必有

∣S∣≤max⁡R≈5×104|S|≤\sqrt{\max R}≈5\times10^4∣S∣≤maxR​≈5×104先筛出 5×1045\times10^45×104 内的素数,再尝试从 SSS 的 ⌈LS⌉\lceil \frac{L}{S} \rceil⌈SL​⌉ 倍开始筛去合数,剩下的就是素数。注意特判 111。

#include<cstdio>
#include<cstdlib>
#include<cstring> #define reg register typedef long long ll;
const int inf=1e6+10;
int L,R;
int a[1000010],b[1000010],d[1000010];
int len=0,c,set=0;
int l1,r1,l2,r2,ans1,ans2; void work(){
memset(b,1,sizeof(b));
for(reg int i=2;i<=inf;++i){
if(b[i]){
b[i]=0;a[++len]=i;
for(reg int j=i+i;j<=inf;j+=i)
b[j]=0;
}
}
}
int main(){
work();
while(scanf("%d%d",&L,&R)!=EOF){
l1=r1=l2=r2=0;ans1=0x3f3f3f3f;ans2=-1;
memset(d,1,sizeof(d));
if(L==1) d[0]=0;
for(reg int i=1;i<=len;++i){
c=L/a[i];
//if(ll(a[i]*c)<(ll)L) ++c;
for(reg int j=c<=1?2:c;j<=R/a[i];++j){
int dd=j*a[i]-L;
if(dd>R-L||dd<0) continue;
d[dd]=0;
}
}
for(reg int i=0;i<=R-L;++i)
if(d[i]){
set=i;
break;
}
if(set==-1){
puts("There are no adjacent primes.");
continue;
}
for(reg int i=set+1;i<=R-L;++i)
if(d[i]){
if(i-set<ans1){
ans1=i-set;
l1=set+L;r1=i+L;
}
if(i-set>ans2){
ans2=i-set;
l2=set+L;r2=i+L;
}
set=i;
}
// for(reg int i=0;i<=R-L;++i)
// printf("%d ",d[i]);
// puts("");
if(!l1&&!r1&&!l2&&!r2)
puts("There are no adjacent primes.");
else
printf("%d,%d are closest, %d,%d are most distant.\n",l1,r1,l2,r2);
}
}

题目描述 loj10198\text{loj10198}loj10198

原题来自:NOIP 2012 普及组

已知正整数 nnn 是两个不同的质数的乘积,试求出较大的那个质数。

输入格式

输入只有一行,包含一个正整数 nnn。

输出格式

输出只有一行,包含一个正整数 ppp,即较大的那个质数。

样例输入

21

样例输出

7

数据范围与提示

对于 30%30\%30% 的数据, n≤1000n\leq1000n≤1000;

对于全部数据,6≤n≤2×1096\leq n\leq 2\times10^96≤n≤2×109。

Solution 10198\text{Solution 10198}Solution 10198

由于 nnn 是 222 个素数之积,所以当我们找到一个较小素数 xxx 使 x∣nx|nx∣n 时,另一个素因子就是 nx\frac{n}{x}xn​。

#include<cstdio>
#include<cstdlib>
#include<cstring> #define reg register typedef long long ll;
ll n;
bool b[200000010]; #define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y)) void work(){
memset(b,1,sizeof(b));
for(reg ll i=2;i*i<=n;++i){
if(b[i]){
b[i]=0;
if(!(n%i)){
printf("%lld",max(i,n/i));
exit(0);
}
for(reg ll j=i+i;j<=min(n,20000000);j+=i)
b[j]=0;
}
}
}
int main(){
scanf("%lld",&n);
work();
}

题目描述 loj10200\text{loj10200}loj10200

哥德巴赫猜想:任何大于 444 的偶数都可以拆成两个奇素数之和。

你的任务是:验证小于 10610^6106 的数满足哥德巴赫猜想。

输入格式

多组数据,每组数据一个 nnn。

读入以 000 结束。

输出格式

对于每组数据,输出形如 n=a+bn=a+bn=a+b,其中 a,ba,ba,b 是奇素数。若有多组满足条件的 a,ba,ba,b,输出 b−ab-ab−a 最大的一组。

若无解,输出 Goldbach's conjecture is wrong.

样例输入

8
20
42
0

样例输出

8 = 3 + 5
20 = 3 + 17
42 = 5 + 37

数据范围与提示

对于全部数据,6≤n≤1066\leq n\leq10^66≤n≤106。

Solution 10200\text{Solution 10200}Solution 10200

  1. 预处理出 1−n1-n1−n 的素数;
  2. 对于每一个 nnn,枚举 aaa 判断是否合法。
#include<cstdio>
#include<cstdlib>
#include<cstring> #define reg register int n,s;
int a[100010],b[1000010];
int len=0;
int f[1000010]; void reset(){
memset(b,1,sizeof(b));
for(reg int i=2;i*i<=1000000;++i)
if(b[i]){
a[++len]=i;
for(reg int j=i+i;j<=1000000;j+=i)
b[j]=0;
}
}
void work(int x){
if(!x) return;
if(f[x]){
printf("%d = %d + %d\n",x,f[x],x-f[x]);
return;
}
for(reg int i=2;i<=len/2+1;++i)
if(b[x-a[i]]){
f[x]=a[i];
printf("%d = %d + %d\n",x,f[x],x-f[x]);
return;
}
}
int main(){
memset(f,0,sizeof(f));
reset();
do{
scanf("%d",&s);
work(s);
}while(s);
}

题目描述 loj10201\text{loj10201}loj10201

Sherlock 有了一个新女友(这太不像他了!)。情人节到了,他想送给女友一些珠宝当做礼物。

他买了 nnn 件珠宝。第 iii 件的价值是 i+1i+1i+1。那就是说,珠宝的价值分别为 2,3,4,...,n+12,3,4,...,n+12,3,4,...,n+1。

Watson 挑战 Sherlock,让他给这些珠宝染色,使得一件珠宝的价格是另一件的质因子时,两件珠宝的颜色不同。并且,Watson 要求他最小化颜色的使用数。

请帮助 Sherlock 完成这个简单的任务。

输入格式

只有一行一个整数 nnn,表示珠宝件数。

输出格式

第一行一个整数 kkk,表示最少的染色数;

第二行 nnn 个整数,表示第 111 到第 nnn 件珠宝被染成的颜色。若有多种答案,输出任意一种。

样例输入 1

3

样例输出 1

2
1 1 2

样例输入 2

4

样例输出 2

2
2 1 1 2

样例说明

因为 222 是 444 的一个质因子,因此第一件珠宝与第三件珠宝的颜色必须不同。

数据范围与提示

对于全部数据,1≤n≤1051\leq n\leq10^51≤n≤105。

Solution 10201\text{Solution 10201}Solution 10201

易证,所有的素数都是互素的。

所以,我们可以把所有的素数全部染成一种颜色,把其他数染成另一种颜色。

#include<cstdio>
#include<cstdlib>
#include<cstring> #define reg register int n;
int a[100010]; void work(){
memset(a,1,sizeof(a));
for(reg int i=2;i<=n+5;++i)
if(a[i])
for(reg int j=i+i;j<=n+5;j+=i)
a[j]=0;
}
int main(){
scanf("%d",&n);
if(n==1){
puts("1\n1");
exit(0);
}
if(n==2){
puts("1\n1 1");
exit(0);
}
work();
puts("2");
for(reg int i=1;i<=n;++i)
printf("%d ",a[i+1]?1:2);
}

题目描述 luoguP1306\text{luoguP1306}luoguP1306

对于Fibonacci数列:1,1,2,3,5,8,13......1,1,2,3,5,8,13......1,1,2,3,5,8,13...... 大家应该很熟悉吧~~~但是现在有一个很“简单”问题:第 nnn 项和第 mmm 项的最大公约数是多少?

输入格式

两个正整数 nnn 和 mmm。(n,m≤109n,m\leq10^9n,m≤109)

输出格式

fnf_nfn​ 和 fmf_mfm​ 的最大公约数。

由于看了大数字就头晕,所以只要输出最后的8位数字就可以了。

输入样例

4 7

输出样例

1

Solution P1306\text{Solution P1306}Solution P1306

今有结论gcd⁡(fn,fm)=fgcd⁡(n,m)\gcd(f_n,f_m)=f_{\gcd(n,m)}gcd(fn​,fm​)=fgcd(n,m)​

证明: 当 n=mn=mn=m 时,结论显然成立。不妨设 n&lt;mn&lt; mn<m,记 fn=a,fn+1=bf_n=a,f_{n+1}=bfn​=a,fn+1​=b。

则fn+2=a+bf_{n+2}=a+bfn+2​=a+bfn+3=a+2bf_{n+3}=a+2bfn+3​=a+2bfn+4=2a+3bf_{n+4}=2a+3bfn+4​=2a+3b.........fm=a⋅fm−n−1+b⋅fm−nf_m=a·f_{m-n-1}+b·f_{m-n}fm​=a⋅fm−n−1​+b⋅fm−n​

而gcd⁡(fn,fm)=gcd⁡(fn,a⋅fm−n+1+b⋅fm−n)\gcd(f_n,f_m)=\gcd(f_n,a·f_{m-n+1}+b·f_{m-n})gcd(fn​,fm​)=gcd(fn​,a⋅fm−n+1​+b⋅fm−n​)

∴gcd⁡(fn,fm)=gcd⁡(fn,b⋅fm−n)\therefore\gcd(f_n,f_m)=\gcd(f_n,b·f_{m-n})∴gcd(fn​,fm​)=gcd(fn​,b⋅fm−n​)。

引理:对于 ∀n∈Z∗\forall n\in\Z^*∀n∈Z∗,有 gcd⁡(fn,fn+1)=1\gcd(f_n,f_{n+1})=1gcd(fn​,fn+1​)=1。

证明: gcd⁡(fn,fn+1)=gcd⁡(fn,fn+fn−1)=gcd⁡(fn,fn−1)=gcd⁡(fn−1,fn−1+fn−2)=gcd⁡(fn−1,fn−2)…=gcd⁡(f2,f1)=1\begin{aligned}\gcd(f_n,f_{n+1})&amp;=\gcd(f_n,f_n+f_{n-1})\\
&amp;=\gcd(f_n,f_{n-1})\\
&amp;=\gcd(f_{n-1},f_{n-1}+f_{n-2})\\
&amp;=\gcd(f_{n-1},f_{n-2})\\
&amp;…\\
&amp;=\gcd(f_2,f_1)\\
&amp;=1
\end{aligned}gcd(fn​,fn+1​)​=gcd(fn​,fn​+fn−1​)=gcd(fn​,fn−1​)=gcd(fn−1​,fn−1​+fn−2​)=gcd(fn−1​,fn−2​)…=gcd(f2​,f1​)=1​

∴\therefore∴gcd⁡(fn,fm)=gcd⁡(fn,fm−n)=gcd⁡(fn,fmmod&ThinSpace;&ThinSpace;n)\begin{aligned}\gcd(f_n,f_m)&amp;=\gcd(f_n,f_{m-n})\\
&amp;=\gcd(f_n,f_{m\mod n})
\end{aligned}gcd(fn​,fm​)​=gcd(fn​,fm−n​)=gcd(fn​,fmmodn​)​

我们发现,这实质就是求解 gcd⁡(m,n)\gcd(m,n)gcd(m,n) 的过程,

∴\therefore∴gcd⁡(fn,fm)=gcd⁡(fgcd⁡(n,m),f0)=fgcd⁡(n,m)\begin{aligned}\gcd(f_n,f_m)&amp;=\gcd(f_{\gcd(n,m)},f_0)\\
&amp;=f_{\gcd(n,m)}
\end{aligned}gcd(fn​,fm​)​=gcd(fgcd(n,m)​,f0​)=fgcd(n,m)​​

于是问题转化成求 fgcd⁡(n,m)f_{\gcd(n,m)}fgcd(n,m)​ 的值。使用矩阵乘法和快速幂完成求解。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> #define reg register typedef long long ll; int a,b;
int n,m; struct node{
ll a[3][3];
int x,y;
node(){
x=y=0;
memset(a,0,sizeof(a));
}
void pt(){
printf("%lld",a[1][2]);
}
}s,t,ans;
node T(node a,node b){
node c;c.x=a.x;c.y=b.y;
for(reg int i=1;i<=c.x;++i)
for(reg int j=1;j<=c.y;++j)
for(reg int k=1;k<=a.y;++k)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%m;
return c;
}
node QT(node a,int b){
if(b<=1) return a;
node c=QT(a,b/2);
if(b%2)
return T(T(c,c),a);
else
return T(c,c);
} int main(){
scanf("%d%d",&a,&b);
n=std::__gcd(a,b);m=100000000;
if(n<=2){
puts("1");
exit(0);
}
s.x=1;s.y=2;s.a[1][1]=s.a[1][2]=1;
t.x=2;t.y=2;t.a[1][1]=0;t.a[1][2]=t.a[2][1]=t.a[2][2]=1;
ans=T(s,QT(t,n-2));
ans.pt();
}

Miller-Rabin 测试

这儿进行预习。

Miller-Rabin 测试基于以下定理。

若 ppp 是素数,xxx 是小于 ppp 的正整数,且 x2mod&ThinSpace;&ThinSpace;p=1x^2\mod p=1x2modp=1,则 x=1x=1x=1 或 x=p−1x=p-1x=p−1。

以 n=341n=341n=341 为例,Miller-Rabin 测试步骤如下:

  1. 计算得 2341−1mod&ThinSpace;&ThinSpace;341=12^{341-1}\mod 341=12341−1mod341=1;
  2. 将 341341341 除以 222,得到 170170170;
  3. 计算得 2170−1mod&ThinSpace;&ThinSpace;341=12^{170-1}\mod 341=12170−1mod341=1;
  4. 将 170170170 除以 222,得到 858585;
  5. 计算得 285mod&ThinSpace;&ThinSpace;341=32≠12^{85} \mod341=32\ne1285mod341=32̸​=1,所以 341341341 不是素数(341341341 是伪素数)。
  6. * 若是素数,则换用 333 或其他素数重复以上操作。

一般地,我们把 ∀n\forall n∀n 有 a(n−1)mod&ThinSpace;&ThinSpace;n=1a^{(n-1)}\mod n=1a(n−1)modn=1 的合数 nnn 叫做以 aaa 为底的 伪素数

素数与Miller-Rabin测试的更多相关文章

  1. 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)

    关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...

  2. 与数论的厮守01:素数的测试——Miller Rabin

    看一个数是否为质数,我们通常会用那个O(√N)的算法来做,那个算法叫试除法.然而当这个数非常大的时候,这个高增长率的时间复杂度就不够这个数跑了. 为了解决这个问题,我们先来看看费马小定理:若n为素数, ...

  3. Miller Rabin算法详解

    何为Miller Rabin算法 首先看一下度娘的解释(如果你懒得读直接跳过就可以反正也没啥乱用:joy:) Miller-Rabin算法是目前主流的基于概率的素数测试算法,在构建密码安全体系中占有重 ...

  4. POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  5. HDU1164_Eddy&#39;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 ...

  6. 【数论基础】素数判定和Miller Rabin算法

    判断正整数p是否是素数 方法一 朴素的判定   

  7. POJ2429_GCD &amp; LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】

    GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 ...

  8. POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  9. Miller Rabin素数检测与Pollard Rho算法

    一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...

  10. (Miller Rabin算法)判断一个数是否为素数

    1.约定 x%y为x取模y,即x除以y所得的余数,当x<y时,x%y=x,所有取模的运算对象都为整数. x^y表示x的y次方.乘方运算的优先级高于乘除和取模,加减的优先级最低. 见到x^y/z这 ...

随机推荐

  1. PHP开发 高可用 高安全App后端(免费)

    PHP开发高可用高安全App后端 第1章 本章先讲解课程所含技术点,并演示相关的项目,让小伙伴对课程有个初步的认知,然后再带领小伙伴进行功能的分析,表的ER总关系图 第2章 本章主要讲解课程的一些准备 ...

  2. Nginx缓存原理及机制

    文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 上篇文章介绍了Nginx一个较为重要的知识点:Nginx实现接口限流.本篇文章将介绍Nginx另一个重要知识点 ...

  3. 首次GitHub千星项目提交维护成功 留念

    现在有点激动,可能有混乱的地方.请大家见谅. 一直觉得千星项目,对我来说是一个遥不可及的地方.没想到第一次在GitHub上 提交Pull Request 就成功了,并且是一个千星项目. 虽然 只是提出 ...

  4. swagger2的简单使用

    swagger2的简单使用 优点: 可以生成文档形式的API并提供给不同的团队使用 便于自己单测 无需过多冗余的word文档,这一点很重要,因为我在工作中就遇到这么一个情况,由于开发使用的文档和最新文 ...

  5. 2019-2020-1 20199303《Linux内核原理与分析》第三周作业

    操作系统是如何工作的 除了存储程序计算机和函数调用堆栈机制,还有一个非常基础的概念就是中断,这三个关键性的方法机制可以称作计算机的三个法宝:程序存储计算机.函数调用.中断 堆栈的作用:记录函数调用框架 ...

  6. android系统中对ffmpeg封装最好的免费SDK

    android系统中对ffmpeg封装最好的免费SDK; 无论个人还是公司,都免费商用, 欢迎下载. https://github.com/LanSoSdk/LanSoEditor_common 可能 ...

  7. kubeadm部署高可用集群Kubernetes 1.14.1版本

    Kubernetes高可用集群部署 部署架构: Master 组件: kube-apiserver Kubernetes API,集群的统一入口,各组件协调者,以HTTP API提供接口服务,所有对象 ...

  8. python句柄部分操作

    ```python3# 通过窗口类名.窗口标题获取控件句柄hwnd = win32gui.FindWindow("ClassName", "TitleName" ...

  9. Docker 本地私有仓库搭建:

    Docker 本地私有仓库搭建: 创建数据卷目录: mkdir /home/sky/registry 用registry镜像启动容器: docker run -d -p 5000:5000 -v /h ...

  10. IDEA 学习笔记之 Python项目开发

    Python项目开发: 下载Python: https://www.python.org/downloads/release/python-363/ 安装Python: 配置环境变量(path): C ...