挑战程序设计讲义竞赛求素数算法
《挑战程序设计竞赛1》题解合集
《挑战程序设计竞赛1》题解合集《挑战程序设计竞赛1》 v2 (papamelon 中⽂题⾯)第 1 章:蓄势待发——准备篇第 2 章:初出茅庐——初级篇 - 2.1 穷竭搜索第 2 章:初出茅庐——初级篇 - 2.2 贪⼼算法213. 字典序最⼩问题 Best Cow Line(挑战程序设计竞赛) todo214. 萨鲁曼的军队 Saruman's Army(挑战程序设计竞赛)todo第 2 章:初出茅庐——初级篇 - 2.3 动态规划第 2 章:初出茅庐——初级篇 - 2.4 数据结构第 2 章:初出茅庐——初级篇 - 2.5 图论第 2 章:初出茅庐——初级篇 - 2.6 数学与数论第 2 章:初出茅庐——初级篇 - 2.7 挑战 GCJ 的题⽬第 2 章:初出茅庐——初级篇 - 课后习题 - 深度优先搜索第 2 章:初出茅庐——初级篇 - 课后习题 - ⼴度优先搜索第 2 章:初出茅庐——初级篇 - 课后习题 - 穷竭搜索第 2 章:初出茅庐——初级篇 - 课后习题 - 贪⼼(区间)第 2 章:初出茅庐——初级篇 - 课后习题 - 贪⼼(其他)第 2 章:初出茅庐——初级篇 - 课后习题 - 动态规划(基础)第 2 章:初出茅庐——初级篇 - 课后习题 - 动态规划(优化递推关系式)第 2 章:初出茅庐——初级篇 - 课后习题 - 动态规划(更困难的)第 3 章:出类拔萃——中级篇 - 3.1 ⼆分搜索第 3 章:出类拔萃——中级篇 - 3.2 常⽤技巧精选(⼀)第 3 章:出类拔萃——中级篇 - 3.3 数据结构第 3 章:出类拔萃——中级篇 - 3.4 动态规划英⽂题⾯的题解《挑战程序设计竞赛1》2.1 poj 1979 Red and Black2.1 Curling 2.02.1 Meteor Showerdfsdfs2.2 poj 1328 Radarinstallation2.2 poj 2393 Yogurt factory2.2 poj 3040 Allowance。
NOIP初赛复习——一些基本算法_强烈推荐
一些基本算法(强烈推荐)一、数论算法1.求两数的最大公约数function gcd(a,b:integer):integer;beginif b=0 then gcd:=aelse gcd:=gcd (b,a mod b);end ;2.求两数的最小公倍数function lcm(a,b:integer):integer;beginif a<b then swap(a,b);lcm:=a;while lcm mod b>0 do inc(lcm,a);end;补充:最小公倍数=a*b div 最大公约数3.素数的求法A.小范围内判断一个数是否为质数:function prime (n: integer): Boolean;var I: integer;beginfor I:=2 to trunc(sqrt(n)) doif n mod I=0 then beginprime:=false; exit;end;prime:=true;end;B.判断longint范围内的数是否为素数(包含求50000以内的素数表):procedure getprime;vari,j:longint;p:array[1..50000] of boolean;beginfillchar(p,sizeof(p),true);p[1]:=false;i:=2;while i<50000 do beginif p[i] then beginj:=i*2;while j<50000 do beginp[j]:=false;inc(j,i);end;end;inc(i);end;l:=0;for i:=1 to 50000 doif p[i] then begininc(l);pr[l]:=i;end;end;{getprime}function prime(x:longint):integer;var i:integer;beginprime:=false;for i:=1 to l doif pr[i]>=x then breakelse if x mod pr[i]=0 then exit; prime:=true;end;{prime}another method:(开素数表)(maxn=1000000)fillchar(a,sizeof(a),true);for i:=2 to trunc(sqrt(maxn)) dofor j:=i to maxn div i doa[i*j]:=false;program life;beginrepeatsurpass myself;until 0=1;end.二、图论算法1.最小生成树A.Prim算法:procedure prim(v0:integer);varlowcost,closest:array[1..maxn] of integer;i,j,k,min:integer;beginfor i:=1 to n do beginlowcost[i]:=cost[v0,i];closest[i]:=v0;end;for i:=1 to n-1 do begin{寻找离生成树最近的未加入顶点k}min:=maxlongint;for j:=1 to n doif (lowcost[j]<min) and (lowcost[j]<>0) then beginmin:=lowcost[j];k:=j;end;lowcost[k]:=0; {将顶点k加入生成树}{生成树中增加一条新的边k到closest[k]}{修正各点的lowcost和closest值}for j:=1 to n doif cost[k,j]<lwocost[j] then beginlowcost[j]:=cost[k,j];closest[j]:=k;end;end;end;{prim}B.Kruskal算法:(贪心)按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。
c语言课程设计素数问题
c语言课程设计素数问题一、教学目标本课程旨在通过C语言编程,让学生掌握素数问题的算法设计与实现。
具体目标如下:1.理解素数的基本概念。
2.掌握素数生成算法。
3.理解素数在计算机科学中的应用。
4.能够使用C语言编写简单的素数生成程序。
5.能够对已有的素数生成算法进行分析和改进。
情感态度价值观目标:1.培养学生对数学和计算机科学的兴趣。
2.培养学生独立思考和解决问题的能力。
二、教学内容1.素数的概念和性质。
2.素数生成算法介绍。
3.C语言编程基础。
4.素数问题的C语言实现。
5.素数生成算法的改进和优化。
6.C语言基础知识(第一章)。
7.素数的概念和性质(第二章)。
8.素数生成算法介绍(第三章)。
9.素数问题的C语言实现(第四章)。
10.素数生成算法的改进和优化(第五章)。
三、教学方法针对不同的教学内容,采用多种教学方法,如讲授法、案例分析法、实验法等。
1.素数的概念和性质:采用讲授法,通过讲解和示例让学生理解素数的基本概念和性质。
2.素数生成算法介绍:采用案例分析法,通过分析已有的素数生成算法,让学生理解其原理和优缺点。
3.C语言编程基础:采用实验法,让学生动手编写C语言程序,掌握C语言的基本语法和编程技巧。
4.素数问题的C语言实现:采用项目驱动法,让学生独立完成素数生成程序的设计和实现。
5.素数生成算法的改进和优化:采用讨论法,让学生分组讨论和分析不同算法的优劣,并提出改进和优化的方案。
四、教学资源1.教材:《C语言程序设计》。
2.参考书:《C语言编程思想》。
3.多媒体资料:教学PPT、视频教程。
4.实验设备:计算机。
以上教学资源将贯穿整个教学过程,为学生提供丰富的学习材料和实践机会。
五、教学评估本课程的教学评估将采用多元化评价方式,全面客观地评估学生的学习成果。
具体评估方式如下:1.平时表现:通过课堂参与、提问、讨论等方式评估学生的学习态度和积极性。
2.作业:布置适量的编程作业,评估学生的编程能力和对知识的掌握程度。
ACM数论01-素数(质数)的判断
ACM数论01-素数(质数)的判断⽤代码判断素数(质数)素数,⼜名质数。
它的定义很简单:在⼤于1的⾃然数中,只有1和它本⾝两个因⼦的数,就是素数(质数)。
注:本⼈喜欢⽤质数这个名字,所以下⽂中都⽤质数代表素数质数的名字叫prime number,所以在代码中,我们对质数总是使⽤prime进⾏变量的命名,对质数判断的函数也会变成isprime()(是质数吗?)或者⼲脆⽤简写isp()根据定义,我们可以很轻松的写出判断⼀个质数的代码:(c++):bool isp(int n){for(int i = 2; i < n; i++){if(n % i == 0) return false;}return true;}(java):static boolean isp(int n){for(int i = 2; i < n; i++){if(n % i == 0) return false;}return true;}这⾥默认不考虑1到底是不是质数,因为1本⾝就不存在质数的定义中。
这样写是可以判断是否是质数的,但如果你了解过时间复杂度,你就会喊出:我的⽼天爷啊!这也太慢了!判断⼀个质数的时间复杂度⾼达了:O(N)如何更加快速地判断⼀个数是否是质数?这⾥我们要引⼊⼀个显⽽易见的论据。
如果⼀个数n能被d整除(或者说d整除n),那么n也⼀定能被n/d整除我们⽤数学符号表⽰:d|n⇒n d|n|是整除符号,表⽰右边的数可以被左边的数整除我们举个例⼦理解吧:3|18⇒183|183可以整除18,18/3也可以整除18,这是显⽽易见的。
因为如果存在⼀个⼤于1的⾃然数,它就⼀定能写成如下的形式:N=A∗B哪怕是质数,也可以写成1*本⾝的形式,如果它是个合数,那么A和B必定不是1和本⾝。
那么从这个显⽽易见的结论,我们可以推出另⼀个结论:⼀个⼤于1的合数,它的因⼦除了1和本⾝以外,总是成对出现的,不过这⼀对可能是⼀样的数,⽐如36=6*6。
挑战程序设计竞赛 求素数算法
return 1; }
int main() { int i, n=1000, num = 0;
for(i=2; i<=n; i++) {
if(is_prime(i)) printf("%3d ",i); } return 0; }
接着再将3的倍数筛去,得到如图-B所示结果。 接下来继续将5的倍数筛去,得到图-C所示结果。 最后再将7的倍数筛去,得到如图-D所示结果,即可得 到100以内的所有素数。
原理很简单,就是当i是素数的时候,i的所有的倍数必 然是合数。如果i已经被判断不是素数了,那么再找到i后面 的素数来把这个素数的倍数筛掉。
这时可考虑采用另一种寻找素数的算法:著名的筛法 (Eratosthenes)求素数方法。
二、 筛法 Eratoslhenes算法假设有一个筛子,用来存放2~100之
间的所有数。 由于偶数都能被2整数,因此偶数都不是素数(2除外),
则将这些数筛去,得到如图-A所示的数据(设置了背景色的 数字将被筛去)
验证一个自然数是否为素数,这个问题早在中世纪就 引起人们的注意,当时人们还在寻找一个公式可以一劳永 逸地解决求素数的问题,直到高斯提出了素数产生的不确 定性后,人们才认识到没有一个公式可以简单确认素数, 从而人们才转去寻找各种验证素数的方法。
一、试除法 试除法是根据素数的定义得出的一种方法,用需要验证
下面用图来演示如何用这种方法求100以内的素数。
图-A 将2的倍数筛去
图-B 将3的倍数筛去
图-C 将5的倍数筛去
图-D 将Leabharlann 的倍数筛去从前面的图示中可看到,在使用Eratosthenes算法进行 筛选时,只需要执行4次筛选就完成了100以内的素数的筛 选,效率非常高。如果要筛选的数据范围更大,由于只需要 选择已经筛选过的素数对后面的数进行筛选,因此可快速筛 选出后面的素数。Eratosthenes算法比试除法的效率要高得 多。
4、NOIP提高组竞赛复试中需要用到的算法或涉及到知识点
NOIP提高组竞赛复试中需要用到的算法或涉及到知识点具体内容如下:(一)数论1.最大公约数,最小公倍数2.筛法求素数3.mod规律公式4.排列组合数5.Catalan数6.康拓展开7.负进制(二)高精度算法1.朴素加法减法2.亿进制加法减法3.乘法4.除法5.亿进制读入处理6.综合应用(三)排序算法1.冒泡排序2.快速排序3.堆排排序4.归并排序5.选择排序(四)DP(动态规划)1.概念2.解题步骤3.背包类DP4.线性DP5.区间动态规划6.坐标型动态规划(规则类DP)7.资源分配型动态规划8.树型动态规划9.状态压缩的动态规划10.动态规划的一般优化方法(五)图论1.Floyd-Warshall2.Bellman-ford3.SPFA4.dijkstra5.prim6.kruskal7.欧拉回路8.哈密顿环9.flood fill(求图的强连通分量)10.最小环问题(基于floyd)11.Topological sort12.次短路13.次小生成树(六)树1.堆2.二叉排序树3.最优二叉树(哈夫曼树)4.求树的后序遍历5.并查集及应用(七)分治1.二分查找2.二分逼近(注意精度问题)3.二分答案4.快排(见排序算法)5.归并排序(见排序算法)(八)贪心(九)搜索1.BFS2.DFS(十)回溯1.八皇后2.剪枝技巧(十一)其它1.离散化2.KMP3.字符串哈希4.常用字符串函数过程5.位运算6.快速幂。
acm大数分解质因数
ACM大数分解质因数1. 引言在算法竞赛中,ACM(ACM ICPC)是一项广受欢迎的比赛形式。
其中,大数分解质因数是一个常见的题目类型。
本文将介绍大数分解质因数的基本概念、常见解法以及一些优化技巧,帮助读者更好地理解和解决相关问题。
2. 基本概念2.1 质数质数(prime number)指的是只能被1和自身整除的正整数。
例如,2、3、5、7等都是质数,而4、6、8等都不是质数。
2.2 质因数质因数(prime factor)指的是一个数的所有质数因子。
例如,24的质因数为2、2、2、3,可以记作2^3 * 3。
2.3 大数在ACM竞赛中,我们常常需要处理超出普通整数范围的大数。
大数通常用字符串或数组来表示,可以进行各种数值运算。
3. 常见解法3.1 枚举法枚举法是最简单直接的解法,其基本思想是从2开始逐个判断是否为质因数。
具体步骤如下:1.将待分解的大数存储为num。
2.从2开始,依次判断每个数i是否为num的质因数。
3.若i是num的质因数,则将i存储为结果,并将num除以i,继续判断num是否还有其他质因数。
4.若num无法再被除尽,说明已经找到了所有质因数,结束循环。
枚举法的时间复杂度较高,但对于小规模的输入仍然是可行的。
3.2 分解法分解法是一种改进的解法,其基本思想是先找到一个质因数,然后将该质因数除尽后,再继续寻找下一个质因数。
具体步骤如下:1.将待分解的大数存储为num。
2.从2开始,依次判断每个数i是否为num的质因数。
3.若i是num的质因数,则将i存储为结果,并将num除以i,继续判断num是否还有其他质因数。
4.若num无法再被除尽,说明已经找到了所有质因数,结束循环。
分解法相较于枚举法,减少了不必要的判断,能够更快地找到质因数。
3.3 分解法优化分解法在寻找质因数时,可以优化判断的上界。
具体优化如下:1.将待分解的大数存储为num。
2.从2开始,依次判断每个数i是否为num的质因数。
埃拉托斯特尼筛法求素数
埃拉托斯特尼筛法求素数
埃拉托斯特尼筛法,又称埃氏筛法,是一种由古希腊数学家埃拉齐斯·埃拉托斯特尼发现
的求素数的方法,是素数筛选的一种算法。
埃拉托斯特尼筛法的原理非常简单,要求求出从2开始至某一数之间的全部素数:
首先,将2~N的各数列出来,把2留下,其余全部标记为可以被删去;
其次,将2这个数的倍数全部删去,3留下,其余全部标记为可以被删去;
再次,将3这个数的倍数全部删去,5留下,其余全部标记为可以被删去;
以此类推,将后面所有留下来的数的倍数全部删去,最后剩下来的就是不被其他数整除的数,也就是素数。
优点:埃拉托斯特尼筛法的实现比较容易,消耗的计算资源很少。
它的平均时间复杂度是
O(NloglogN),主要分为把N内的数列出来,把N之内的素数筛选出来两个步骤,把N内
的数列出来
它只需要多次循环,每次把一个数的倍数筛除掉,就能求出一定范围范围内的所有素数,
因此一个与这个时间复杂度十分接近的算法就得到了,运行起来也分显迅速。
缺点:由于这种算法仅仅在某种领域有效,所以不适合多用于多种情况,而且它的时间复
杂度比较高,它要求算法的计算效率有较高的要求,较其他算法程序相比,埃拉托斯特尼
算法的计算时间比较长。
对于程序实现来说,埃拉托斯特尼筛法也需要考虑嵌套和循环方面的知识,并且计算复杂
度高,容易引起算法程序的运行变慢的问题。
总的来说,埃拉托斯特尼筛法是一种很简单的算法,但却有很高的效率,在数学上有着独
特的含义,能使素数筛选算法的计算效率大大的提升,可以说是一个重要的优化筛选算法。
acm程序设计竞赛 数学基础 刘汝佳
数学基础(版本2009)刘汝佳例1. 同构计数•一个竞赛图是这样的有向图–任两个不同的点u、v之间有且只有一条边–不存在自环•用P表示对竞赛图顶点的一个置换。
当任两个不同顶点u、v间直接相连的边的方向与顶点P(u)、P(v)间的一样时,称该图在置换P下同构•对给定的置换P,我们想知道对多少种竞赛图在置换P下同构分析•先把置换它分解成为循环, 首先证明长度为L的偶循环将导致无解–对于点i1, 记P(i k)=i k+1, 假设i1和i L/2+1的边方向为i1->i L/2+1, 那么有i2->i L/2+2, i3->i L/2+3, …, i L/2+1->i1, 和假设矛盾!•假设确定其中k条独立边后其他边也会确定, 则答案为2k•考虑两类边: 循环内边和循环间边.分析•循环内顶点的关系–定了i 1和i j 之间的关系, i k 与i (k+j-2) mod n+1之间的关系也被确定下来了, 因此只需要确定i 1和i 2, i 3, …, i (L-1)/2+1这(L-1)/2对顶点的关系•不同循环间顶点的关系–设循环为(i 1,i 2,…,i L1)和(j 1,j 2,…,j L2), 通过类似分析得只需要确定gcd(L1, L2)对关系即可分析•最后答案为2k1+k2•其中k1=sum{(L-1)/2}, k2=sum{gcd(L1, L2)}•可以用二分法加速求幂例2. 图形变换•平面上有n个点需要依次进行m个变换处理•规则有4种, 分别把(x0,y)变为–平移M(x, y): (x0+x, y0+y)–缩放Z(L): (Lx0, Ly0)–翻转F(0): (x0, -y0); F(1): (-x0, y0)–旋转R(a): a为正时逆时针, 离原点距离不变, 旋转a度•给n(<=106)个点和m(<=106)条指令•求所有指令完成后每个点的坐标分析•如果直接模拟, 每次需要O(n)的时间, 一共O(nm), 无法承受•把点(x0, y)写成列向量[x, y]T, 则后3种变换可以都可以写成矩阵–缩放P’= Z * P, Z = [L 0; 0 L]–翻转P’= F * P, F = [1 0; 0 -1]或[-1 0; 0 1]–旋转P’= R * P, R = [cosa–sina; sina cosa]•可是无法实现平移, 怎么办呢?分析•修改表达方式, 令P = [x 0, y 0, 1]T , 则四种变换的矩阵M, Z, F, R 分别为100001,00001001x L M y Z L ⎡⎤⎡⎤⎢⎥⎢⎥==⎢⎥⎢⎥⎢⎥⎢⎥⎣⎦⎣⎦100100010010001001F −⎡⎤⎡⎤⎢⎥⎢⎥=−⎢⎥⎢⎥⎢⎥⎢⎥⎣⎦⎣⎦或cos sin 0,sin cos 0001a a R a a −⎡⎤⎢⎥=⎢⎥⎢⎥⎣⎦分析•只需要先计算所有变换矩阵的乘积A, 然后对于每个点, P’= A * P•注意: 矩阵乘法不满足交换律, 因此需要按照输入顺序进行乘法•每次矩阵乘法需要33=27次乘法, 则计算A一共需要27m次乘法, 对所有点变换需要27n 次乘法, 一共27(n+m)次例3. 染色方案•N*M(N<=10100, M<=5)的格子纸,每个格子被填上黑色或者白色。
素数和环_计算机常用算法与程序设计教程(第2版)_[共4页]
// 往前回溯
if(a[i]==9 && i==1) break; else a[i]++;
// 至第 1 个数为 9 结束
} printf("\n 共搜索到以上%d 个分数式。\n",s);
}
3.程序运行示例与变通
1: 1/29+7/406=3/58
2: 1/39+4/780=2/65
3: 2/17+5/340=9/68
printf("%ld=%d/%ld",m2,a[8],m3);
if(s%2==0) printf("\n");
// 每一行控制输出 2 个分数式
} } } if(i<10 && g==1) { i++;a[i]=0;continue;}
// 不到 10 个数,往后继续
while(a[i]==9 && i>1) i--;
4: 2/95+4/760=1/38
5: 484+2/315=7/90
7: 7/58+9/406=3/21
8: 8/45+9/162=7/30
9: 9/72+1/504=8/63
共搜索到以上 9 个分数式。
以上 10 数字分数式求解是在 9 数字分数式设计基础上变通所得,结构基本相同。请比较以上 两个回溯设计的参数变化。
计算机常用算法与程序设计教程(第 2 版)
m3=a[9]*10+a[10]; if(a[1]*m2*m3+a[4]*m1*m3==a[8]*m1*m2)
// 判断等式
c语言求素数课程设计
c语言求素数课程设计一、课程目标知识目标:1. 学生能理解素数的定义,掌握判断素数的基本方法。
2. 学生能运用C语言编写程序,实现求素数的功能。
3. 学生了解素数在数学和计算机科学中的应用。
技能目标:1. 学生掌握C语言循环、判断等基本语法结构,能独立编写求素数的程序。
2. 学生能运用调试工具检查并修正程序中的错误,提高程序的正确性和效率。
3. 学生通过上机实践,提高编程能力和问题解决能力。
情感态度价值观目标:1. 学生对编程产生兴趣,培养良好的编程习惯。
2. 学生在团队协作中,学会沟通、分享和互助,增强团队意识。
3. 学生通过解决实际问题,认识到编程在生活中的应用,激发对计算机科学的热爱。
课程性质:本课程为C语言编程实践课,注重培养学生的编程能力和问题解决能力。
学生特点:学生已具备C语言基本语法知识,有一定的编程基础,但对素数判断方法及编程应用尚不熟悉。
教学要求:教师应结合学生特点,采用任务驱动、启发式教学等方法,引导学生主动探索、实践,提高学生的编程技能和实际应用能力。
在教学过程中,注重培养学生的团队合作意识和情感态度价值观。
通过本课程的学习,使学生在知识、技能和情感态度价值观方面均取得具体的学习成果。
二、教学内容1. 素数概念介绍:通过讲解素数的定义,让学生理解什么是素数,以及素数在数学中的重要性。
2. 判断素数的方法:分析并介绍常见的判断素数的方法,如试除法、埃拉托斯特尼筛法等,为学生编写程序打下基础。
3. C语言编程基础:回顾C语言中的循环结构(for、while)、条件判断(if-else)、函数定义等基本语法,为编写求素数程序提供支持。
4. 编写求素数程序:根据素数判断方法,引导学生使用C语言编写求素数的程序,并针对不同范围(如100以内的素数)进行讨论。
5. 程序调试与优化:教授学生如何使用调试工具(如GDB)查找并修正程序中的错误,提高程序的正确性和效率。
6. 素数应用拓展:介绍素数在密码学、计算机科学等领域的应用,激发学生深入学习的兴趣。
ACM程序设计竞赛例题[1]
A C M程序设计竞赛例题[1]-CAL-FENGHAI.-(YICAI)-Company One1备战ACM资料习题1.0-1背包问题在0 / 1背包问题中,需对容量为c 的背包进行装载。
从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。
对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。
程序如下:#include <>void readdata();void search(int);void checkmax();void printresult();int c=35, n=10; ");printf("\n");}printf("\n");}6.素数环问题把从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。
分析:用回溯算法,考察所有可能的排列。
程序如下:#include <>#include <>void search(int);void init(); 表示空格;’X’表示墙。
程序如下:#include <>#include <>void search(int,int);int canplace(int,int);void readdata(); Floodfill给一个20×20的迷宫和一个起点坐标,用广度优先搜索填充所有的可到达的格子。
提示:参考第2题。
2. 电子老鼠闯迷宫如下图12×12方格图,找出一条自入口(2,9)到出口(11,8)的最短路本题给出完整的程序和一组测试数据。
状态:老鼠所在的行、列。
程序如下:#include<>void readdata();a[i][j]=0; ....注:测试数据可在运行时粘贴上去(点击窗口最左上角按钮,在菜单中选则“编辑”/“粘贴”即可)。
C语言求素数成绩算法
如何求素数1.自然数是0,1,2……2.素数是2,3,5……(不包括1的只能背1和它本身整除的自然数)【1】求10000以内的所有素数。
素数是除了1和它本身之外再不能被其他数整除的自然数。
由于找不到一个通项公式来表示所有的素数,所以对于数学家来说,素数一直是一个未解之谜。
像著名的哥德巴赫猜想、孪生素数猜想,几百年来不知吸引了世界上多少优秀的数学家。
尽管他们苦心钻研,呕心沥血,但至今仍然未见分晓。
自从有了计算机之后,人们借助于计算机的威力,已经找到了2216091以内的所有素数。
求素数的方法有很多种,最简单的方法是根据素数的定义来求。
对于一个自然数N,用大于1小于N的各个自然数都去除一下N,如果都除不尽,则N为素数,否则N为合数。
但是,如果用素数定义的方法来编制计算机程序,它的效率一定是非常低的,其中有许多地方都值得改进。
第一,对于一个自然数N,只要能被一个非1非自身的数整除,它就肯定不是素数,所以不必再用其他的数去除。
第二,对于N来说,只需用小于N的素数去除就可以了。
例如,如果N能被15整除,实际上就能被3和5整除,如果N不能被3和5整除,那么N也决不会被15整除。
第三,对于N来说,不必用从2到N一1的所有素数去除,只需用小于等于√N(根号N)的所有素数去除就可以了。
这一点可以用反证法来证明:如果N是合数,则一定存在大于1小于N的整数d1和d2,使得N=d1×d2。
如果d1和d2均大于√N,则有:N=d1×d2>√N×√N=N。
而这是不可能的,所以,d1和d2中必有一个小于或等于√N。
基于上述分析,设计算法如下:(1)用2,3,5,7逐个试除N的方法求出100以内的所有素数。
(2)用100以内的所有素数逐个试除的方法求出10000以内的素数。
首先,将2,3,5,7分别存放在a[1]、a[2]、a[3]、a[4]中,以后每求出一个素数,只要不大于100,就依次存放在A数组中的一个单元中。
经典算法题目
【程序1】题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?1.程序分析:兔子的规律为数列1,1,2,3,5,8,13,21....public class exp2{public static void main(String args[]){int i=0;for(i=1;i<=20;i++)System.out.println(f(i)); }public static int f(int x) {if(x==1 || x==2) return 1;else return f(x-1)+f(x-2); } }【程序2】题目:判断101-200之间有多少个素数,并输出所有素数。
1.程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。
【程序3】题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身。
例如:153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方。
1.程序分析:利用for循环控制100-999个数,每个数分解出个位,十位,百位。
【程序4】题目:将一个正整数分解质因数。
例如:输入90,打印出90=2*3*3*5。
程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成:(1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。
(2)如果n <> k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。
(3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。
【程序5】题目:利用条件运算符的嵌套来完成此题:学习成绩> =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。
奥林匹克数学题型素数分布
奥林匹克数学题型素数分布素数一直是数学研究中的一个重要课题,不仅仅在数论中有着举足轻重的地位,同时也在奥林匹克数学竞赛中扮演着重要的角色。
本文将探讨奥林匹克数学竞赛中与素数相关的题型,以及素数在数学题目中的分布特点。
1. 素数的定义及性质首先,我们来回顾一下素数的定义。
素数是指大于1的自然数,除了1和自身外没有其他正因数的数。
素数具有以下性质:- 素数只能被1和自身整除,没有其他因数;- 除了2之外,所有的素数都是奇数;- 每个大于2的偶数都可以分解成两个素数的和,即哥德巴赫猜想。
2. 奥林匹克数学竞赛中的素数题型在奥林匹克数学竞赛中,素数题型通常涉及到素数的性质和分布规律。
以下是一些常见的题型:2.1. 素数的性质题目这类题目要求考生深入理解素数的定义和性质,解决一些关于素数的等式、不等式等数论问题。
通过这类题目的解答,考生能够更好地掌握素数的特性。
2.2. 素数的分布题目这类题目要求考生探究素数在某个范围内的分布规律。
比如,给定一个正整数n,要求计算出在1到n之间的素数个数。
通过解答这类题目,考生可以观察素数的分布情况,发现一些规律,提高数论的思维能力。
3. 素数分布的规律和猜想素数的分布一直以来都是数学家和研究者们关注的问题。
尽管素数的分布并不规则,但在奥林匹克数学竞赛中,我们可以观察到一些有趣的规律。
3.1. 素数定理素数定理是数论中的一个重要定理,它描述了素数分布的大致情况。
素数定理由法国数学家欧拉于18世纪提出,它表明在充分大的范围内,小于等于正整数n的素数个数约为n/ln(n)。
3.2. 筛法筛法是一种用于找出一定范围内的素数的方法。
其中最常见的是埃拉托斯特尼筛法,它的基本思想是从2开始,依次将素数的倍数筛去,最终得到素数的集合。
3.3. 素数分布猜想尽管素数分布没有明确的规律,但数学家们提出了一些猜想。
比如,孪生素数猜想认为存在无限多对相邻的素数,它们之间的差值为2。
黎曼猜想则探讨了素数分布与复数解析函数的关系。
求出200——1000之间所有的素数
C语言程序设计综合实验报告学院:信息科学与工程学院专业:自动化1002班学号:201004134070 姓名:吴君指导老师:2011年6月25日武汉科技大学求出200——1000之间所有的素数,要求1)调用函数判断某数是不是素数;2)输出结果,每行输出十个;程序:#include<stdio.h>#include<math.h>int judge(int n)//定义一个函数{int i,k;k=sqrt(n);for(i=2;i<=k;i++)//判断I是否是素数{if(n%i==0){ break;}}if (i>k){return 1;//返回一个函数值}return 0;}void main(){int i,m,k;for(i=201;i<1000;i=i+2){m=judge(i);//调用自定义函数if (m==1){printf("%4d",i); //输出结果k++;if(k%10==0)//大于10换行printf("\n");}}}输出结果:211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641643 647 653 659 661 673 677 683 691 701709 719 727 733 739 743 751 757 761 769773 787 797 809 811 821 823 827 829 839853 857 859 863 877 881 883 887 907 911919 929 937 941 947 953 967 971 977 983991 997Press any key to continue利用随机函数产生200个正整数,统计这200个正整数中相同的个数。
《挑战程序设计竞赛》---算法初级篇
《挑战程序设计竞赛》---算法初级篇本系列为《挑战程序设计竞赛》读书笔记,分为、、初级篇⽬录:1. 穷竭搜索2. 贪⼼3. 动态规划4. 数据结构5. 图论6. 数论1.穷竭搜索a.核⼼思想:DFS :从某个状态开始,不断转移,直⾄⽆法转移,回退到前⼀步,再继续转移到其他状态,直到找到最终解;⼀般使⽤递归或者栈实现BFS 从初始状态开始,总是先搜索⾄距离初始状态近的状态。
每个状态都只经过⼀次,因此复杂度为O(状态数*转移⽅式数);⼀般使⽤队列实现b.优化细节:剪枝:明确知道从当前状态⽆论如何转移都不会存在解的情况下,不再继续搜索⽽是直接跳过特殊状态枚举:可⾏解空间多数可采⽤DFS,但当其⽐较特殊时,可简短地实现:全排列使⽤STL中的next_permutation组合或⼦集使⽤位运算栈内存与堆内存:(所以⼀般算法竞赛中都使⽤全局数组,开的最⼤)main函数中的局部变量存储在栈内存中,统⼀分配后不再扩⼤,影响栈深度,与机器设置有关。
通常,C++中执⾏上万次递归是可⾏的。
new或malloc的分配的是堆内存,全局变量存储在堆内存中,使⽤全局变量代替局部变量可减少栈溢出的风险。
c.题解POJ 3009: Curling 2.0 :/** POJ 3009: Curling 2.0* 题意:m*n矩阵中,给出起点、终点、空格、障碍,从每个点可向4⽅前进,直到遇到障碍,打碎并停在障碍格的前⾯。
求到达终点的最少前进次数。
* 类型:DFS+记忆化搜索* 算法:从某点出发,向4个⽅向投掷,遇到障碍格,标记其为空格状态,继续递归障碍前⼀点,回退恢复障碍状态。
每次递归直⾄到达终点或全部出界失败。
*/AOJ 0558: Cheese/** AOJ 0558: Cheese* 题意:m*n矩阵内,给出起点、1~N表⽰N个⼯⼚、障碍、空格。
求按顺序遍1~N的最短路。
* 类型:BFS+Queue(/Dijkstra)* 算法:从S顺序通过1~N的最短路,可以⽤BFS求N次相邻序号间最短路的和。
信息学竞赛中质数解法及优化
信息学竞赛中质数解法及优化江西省信息学奥林匹克代表队领队、教练九江市第一中学龚禹作者简介:龚禹,1983年7月毕业于江西大学,从事计算机的相关工作二十余年,积累了丰富的实际工作经验,2002年9月开始投入信息学奥赛的教研工作,三年多来取得了丰硕的教学成果。
他的弟子连续四年获得九江市信息学奥赛普及组第一名,2004年开始率初中生进军高中组,并连续两年获得九江市信息学奥赛提高组第一、二名。
在全国信息学奥林匹克分区联赛(NOIP)与全国信息学奥林匹克竞赛(NOI)上也取得了不俗的成绩,2002年11月率初一学生夺的第八届NOIP普及组一等奖、江西赛区第一名;2004年11月率两名初中学生分夺第十届NOIP提高组一等奖、二等奖,分别入选第22届江西省信息学奥林匹克代表队与同步举办的夏令营队;2005年8月率初中生以248分的成绩夺的第22届全国信息学奥林匹克竞赛(NOI2005)同步夏令营铜奖(全国铜奖分数线为223分),创造了我省初中生在全国高中学科竞赛中获奖的记录。
问题:求小于10000的所有质数。
这是初学者常见的一道问题。
首先,让我们回顾一下质数的定义:如果一个大于1的自然数,只能被1和它本身整除,那么这个自然数就是质数(素数)。
一、枚举方法1. 简单枚举法显然,根据这个质数的定义,我们想到,要判断一个数是否为质数,只要判断所有大于1且小于它的自然数都不能被其整除就可以了。
因此,我们得出了一种解这道题的方法,大体策略为:枚举所有小于10000的数,判断其是否为质数,若是质数则输出。
这种方法我们称之为“枚举法”。
但使用简单枚举法设计的程序运行的时间是漫长的,效率十分低下。
仔细分析,可发现枚举的思路可分为两部分:枚举和判断。
那么,我们能否从这两部分入手,对算法进行改进。
2. 对枚举数字的改进首先是改进枚举,宗旨是尽量不要枚举那些显然不是质数的数。
由于2是质数,那么根据质数的定义,4,6,8,……,都不会是质数。
超级素数搜索_计算机常用算法与程序设计教程(第2版)_[共4页]
58(2)简单逆推算法逆推即从后往前推,从已求得的规模为n,n−1,…,i+1的一系列解,推出问题规模为i的解,直至得到规模为1的解。
简单逆推算法框架描述:f(n~i+1)=<初始值>;// 确定初始值for(k=i;k>=1;k--)f(k)=<递推关系式>;// 根据递推关系实施逆推print(f(1));// 输出目标值f(1)(3)二维数组顺推算法简单递推问题设置一维数组实现,较复杂的递推问题需设置二维或二维以上数组。
设递推的二维数组为f (k,j),1≤k≤n,1≤j≤m,由初始条件分别求得f (1,1),f (1,2),…,f (1,m),则据给定的递推关系由初始条件依次顺推得f (2,1),f (2,2),…, f (2,m);f (3,1),f (3,2),…,f (3,m);…,直至得到目标值f (n,m)。
二维数组顺推算法框架描述:f(1,1~m)=<初始值>;// 赋初始值for(k=2;k<=n;k++)for(j=1;j<=m;j++)f(k,j)=<递推关系式>;// 根据递推关系实施递推print(f(n,m));// 输出目标值f(n,m)(4)多关系分级递推算法当递推关系包含两个或两个以上关系式时,通常应用多关系分级递推求解。
f(1~i-1)=<初始值>;// 赋初始值for(k=i;k<=n;k++){ if(<条件1>)f(k)=<递推关系式1>;// 根据递推关系1实施递推……if(<条件m>)f(k)=<递推关系式m>;// 根据递推关系m实施递推}print(f(n));// 输出目标值f(n)4.递推算法的时间复杂度一般来说,递推算法是一个高效而直接的常用算法。
如果能在一重循环中完成递推,无论是顺推还是逆推,通常其相应的时间复杂度是线性的,即为O(n)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
验证一个自然数是否为素数,这个问题早在中世纪就 引起人们的注意,当时人们还在寻找一个公式可以一劳永 逸地解决求素数的问题,直到高斯提出了素数产生的பைடு நூலகம்确 定性后,人们才认识到没有一个公式可以简单确认素数, 从而人们才转去寻找各种验证素数的方法。
一、试除法 试除法是根据素数的定义得出的一种方法,用需要验证
for(i=2; i<=n; i++)
{
if( n%i==0 ) return 0; //判断n能否被i整除
}
return 1;
} 其实,可以对素数的定义进行进一步的分析。要判断数n
是否为素数,不需要用n一直除到n-1才能确认,而只需要除 到√n 而就可以了。例如,n=15,则能被15整除的除数有1、 3、5,对于除数5就不用判断,因为n被3整除时其商就是5, 也就表示n能被5整除了。
精品jing
挑战程序设计竞赛求素数算法
素数(prime number) ,又称质数,指在大于1的自 然数中,除了1和此整数自身外,无法被其他自然数整除的 数(也可定义为只有1和本身两个因数的数)。
比1大但不是素数的数称为合数。1和0既非素数也非合 数。素数在数论中有着非常重要的地位。
最小的素数是2,也是素数中唯一的偶数;其他素数都 是奇数。素数有无限多个,所以不存在最大的素数。
for(int i=2;i*i<=n;i++) if(n%i==0) return 0;
return 1; }
int main() { int i, n=1000, num = 0;
for(i=2; i<=n; i++) {
if(is_prime(i)) printf("%3d ",i); } return 0; }
这时可考虑采用另一种寻找素数的算法:著名的筛法 (Eratosthenes)求素数方法。
二、 筛法 Eratoslhenes算法假设有一个筛子,用来存放2~100之
间的所有数。 由于偶数都能被2整数,因此偶数都不是素数(2除外),
则将这些数筛去,得到如图-A所示的数据(设置了背景色的 数字将被筛去)
改进后的是否为素数的函数: int is_prime(int n) { int i; if (n<=1) return 0; //n不是素数,返回零 for(i=2; i*i<=n; i++) //for(int i = 2; i <= sqrt(n); ++i) { if( n%i==0 ) return 0; //判断n能否被i整除 } return 1; }
下面用图来演示如何用这种方法求100以内的素数。
图-A 将2的倍数筛去
图-B 将3的倍数筛去
图-C 将5的倍数筛去
图-D 将7的倍数筛去
从前面的图示中可看到,在使用Eratosthenes算法进行 筛选时,只需要执行4次筛选就完成了100以内的素数的筛 选,效率非常高。如果要筛选的数据范围更大,由于只需要 选择已经筛选过的素数对后面的数进行筛选,因此可快速筛 选出后面的素数。Eratosthenes算法比试除法的效率要高得 多。
接着再将3的倍数筛去,得到如图-B所示结果。 接下来继续将5的倍数筛去,得到图-C所示结果。 最后再将7的倍数筛去,得到如图-D所示结果,即可得 到100以内的所有素数。
原理很简单,就是当i是素数的时候,i的所有的倍数必 然是合数。如果i已经被判断不是素数了,那么再找到i后面 的素数来把这个素数的倍数筛掉。
在上面的代码中,通过is_prime()函数来验证指定区间 (2~1000)中的每一个数是否为素数,而is_prime()函数中又 通过循环进行验证。这种双循环会导致程序执行效率不高。
试除法求解n以内素数的算法。复杂度是o(n*sqrt(n)), 如果n很小的话,这种算法不会耗时很多。但是当n很大的时 候,比如n=10000000时,n*sqrt(n)>30000000000,数量级 相当大。在一般的电脑上它不是一秒钟跑不出结果,它是好 几分钟都跑不出结果的。
根据筛法所示的过程编写相应的程序,具体代码如下:
#include <cstdio> #define MAX 1000000 bool prime[MAX]; int main() { int i,j,num=0;
for (i=2;i<MAX;i++) prime[i]=true;
for (i=2;i<MAX;i++) { if(prime[i]) for(j=i+i;j<MAX;j+=i) }
的数n逐个除以从2开始至n-1中的所有数,若能被某一个数 整除,表示有一个因数,说明数n不是素数:若直到n-1都 不能被整除,则说明该数是素数。
根据以上思路,可编写以下的试除法函数:
试除法判断是否为素数的函数:
int is_prime(int n)
{ int i;
if (n<=1) return 0; //n不是素数,返回零
围绕著素数存在很多问题、猜想和定理。著名的有 “孪生素数猜想”和“哥德巴赫猜想”。
关于素数的算法是信息学竞赛和程序设计竞赛中经常出 现的基础算法,虽然题目各不相同,但都要涉及验证一个自 然数是否为素数的问题。下面探讨寻找一定范围内素数的几 个算法。
根据以上思路,可编写以下的试除法函豹:
其实,可以对素数的定义进行进一步的分析。要判断数 n是否为素数,不需要用n一直除到n-1才能确认,而只需要 除到√n 而就可以了。例如,n=15,则能被15整除的除数有 1、3、5,对于除数5就不用判断,因为n被3整除时其商就 是5,也就表示n能被5整除了。
prime[j]=false;
for(i=2;i<MAX;i++) { if(prime[i]==true) { num++; printf("%8d",i); } } printf("\n Total=%d ",num);
改进后的程序中,在for循环中以i*i既i的平方与n值进行 比较,就可以显著地减少循环的次数,提高验证的效率。
这里用了 i*i <= n 来代替 sqrt(n),可以避免调用函数 sqrt(),其消耗时间较多,特别是在大量数据测试的时候消 耗很明显。
求出1000以内的所有素数: #include <cstdio> int is_prime(int n) {