a和b的约数整除他们的余数。
1.“欧几里得”算法求两个数的最大公因数
#include "stdafx.h"
#include
using namespace std;
int main()
{
int a, b,temp=1;
cout << "请输入两个数" << endl;
cin >> a >> b;
while(b!=0)
{
temp = a%b;
a = b;
b = temp;
}
cout <<"最大公倍数为:"<< a<
原理如下:
很早就学过欧几里得算法,但是一直不知道它的原理。几乎每本算法书都会提到它,但是貌似只有数学书上才会见到它的原理。。。
前段时间粗粗看了点数论,惊讶于这个原理的奇妙。现在把它通俗地写下来,以免自己忘记。
欧几里得算法是求两个数的最大公约数(Greatest Common Divisor (GCD))的算法,我们首先假设有两个数 a 和 b,其中 a 是不小于 b 的数,
记 a 被 b 除的余数为 r,那么 a 可以写成这样的形式:
a=bq+r
其中 q 是整数。
现在假设 a 和 b 的一个约数为 u,那么 a 和 b 都能被 u 整除,即
a=su
b=tu
s和t都是整数
这样可以得出
r=a-bq=su-(tu)q=(s-tq)u
所以 r 也能被 u 整除,一般规律如下
a 和 b 的约数也整除它们的余数 r,所以 a 和 b 的任一约数同时也是 b 和 r 的约数。 —— 条件一
反过来可以得出
b 和 r 的任一约数同时也是 a 和 b 的约数。 ——条件二
这是因为对 b 和 r 每一个约数 v,有
b=kv
r=cv
于是有
a=bq+r=(kv)q+cv=(kq+c)v
由条件一和条件二可知
a 和 b 的约数的集合,全等于 b 和 r 的约数的集合。
于是
a 和 b 的最大公约数,就是 b 和 r 的最大公约数。
接下来用递推法,
a ÷ b 余 r,现在设
b ÷ r 余 r1
r ÷ r1 余 r2
……
r(n-3) ÷ r(n-2) 余 r(n-1)
r(n-2) ÷ r(n-1) 余 r(n)
因为 a>=b,可以看出余数 r(n) 会越来越小,最终变成 0.
当 r(n-1)≠0 且 r(n) = 0 时,可知 r(n-2) 可被 r(n-1) 整除,此时他俩的约数就只有:r(n-1) 和 r(n-1) 的因数,所以他们的最大公约数就是 r(n-1)!
所以 r(n-1) 就是 a 和 b 的最大公约数。(若 r = 0,则 b 为最大公约数)
可以发现这里没有要求 M>=N,这是因为如果那样,循环会自动交换它们的值。
转自这里
2.用“艾拉托尼筛选法”求n以内的所有质数
#include "stdafx.h"
#include
#include
using std::cout;
int main()
{
int n,count = 0;
int temp;
printf("查询n以内的质数,请输入n:\n");
scanf("%d", &n);
int* arr=NULL;
try
{
arr = new int[n+1];
}
catch (const std::bad_alloc &e)
{
cout << "申请内存失败" << std::endl;
}
if (arr == 0) // 有的编译器不能捕捉到new申请失败时抛出的异常,所以判断一下arr是否为空
cout << "申请内存失败" << std::endl;
int sqrtn = (int)sqrt(n);
//为数组赋值,将每个数组成员下标分别赋值给自己
for (int i = 0; i <=n; i++)
{
arr[i] = i;
cout << i << std::endl;
}
//利用埃拉托色尼筛选法,将不是质数的数赋值为0
for (int p= 2; p <= sqrtn; p++)
{
temp = p*p;
while (temp <= n)
{
arr[temp] = 0; //用0标志它不是质数
temp = temp + p;
}
}
//打印所有质数
for (int i = 2; i <= n; i++)
{
if (arr[i] != 0)
{
count += 1;
printf("第%d个质数:%d\n",count, i);
}
}
printf("一共有质数%d个", count);
delete arr;
return 0;
}
这里因为是用new来动态申请空间,所以可能会涉及到内存申请失败的可能。
知道new是在堆上面分配空间,是否new申请空间的上限即是堆的上限?new能最多能申请到多少的空间呢?因编译器而异?还是因操作系统而异?或者两者都有?
于是去别人院子里剽窃了一波:
1.栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构的栈。
2.堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。
3.堆和栈的区别:
(1)由以上综述就可以得知,他们程序的内存分配方式不同。
(2)申请和响应不同:
(1)申请方式:
栈:由系统自动分配,系统收回;
堆:需要程序员自己申请,C语言中用函数malloc分配空间,用free释放。
(2)申请后系统的响应:
栈:只要栈的剩余空间大于所申请的空间,体统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间
大于所申请的空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,对于大多
数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码中的delete或free语句就能够正确的释放本
内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会将多余的那部分重新放入空闲链表中。
(3)申请的大小限制不同:
栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域,这是由于系统是由链表在存储空闲内存地址,自然堆就是
不连续的内存区域,且链表的遍历也是从低地址向高地址遍历的,堆得大小受限于计算机系统的有效虚拟内存空间,
由此空间,堆获得的空间比较灵活,也比较大。
(4)申请的效率不同:
栈:栈由系统自动分配,速度快,但是程序员无法控制。
堆:堆是有程序员自己分配,速度较慢,容易产生碎片,不过用起来方便。
(5)堆和栈的存储内容不同:
栈:在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令的地址,然后是函数的各个参数,在大多数的
C编译器中,参数是从右往左入栈的,当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最
开始存的地址,也就是主函数中的下一条指令。
作者:Mormont
来源:CSDN
原文:https://blog.csdn.net/mormont/article/details/53511441
版权声明:本文为博主原创文章,转载请附上博文链接!