利用埃拉托色尼筛法求两个数的最大公约数

思路:

1,求出两个数中较大数的,小于其所有质数数列

2,分别求出两个数的质因数数列以及每个质因数被分解的次数

3,用另一个数列村两个数相同质因数,以及该质因数被分解两个数相比之下的最小次数

4,将上述数列的质因数分别做最小次数的幂并将结果相乘,就是最终的结果最大公约数

说得不够简洁,下面是举例:

n=12 ,m=24

小于m所有质数:2,3,5,7,11,13,17,19,23

n的质因数及次数:质因数 2 次数是 2

                               质因数 3 次数是 1

m的质因数及次数:质因数 2 次数是 3

                               质因数 3 次数是 1

得出两者结果:质因数 2 次数是 2

                        质因数 3 次数是 1

算出来公约数=2*2*3=12

#include<stdio.h>
#define MAX 1000
#define WHAT 1//只是随便取的名字,含义是whatever 
int main(){
	int a[MAX],b[MAX]={0},c[MAX]={0},d[MAX]={0},e[MAX]={0};
	int i,j,k,n,m;
	printf("请输入两个正整数\n");
	scanf("%d%d",&n,&m); 
 
	for(i=0;i<MAX;i++)
	a[i]=WHAT;//将数列全部置成非0 
	
	k=j=0;
	if(n>=m){//找到n和m中稍大数的质数列
for(i=2;i<=n;i++){
		if(a[i]!=0){
			b[k]=i;
			k++;
				for(j=i+i;j<=n;j=j+i)
				a[j]=0;
			
		}
	}
}
	else{
	for(i=2;i<=m;i++){
		if(a[i]!=0){
			b[k]=i;
			k++;
			
			for(j=i+i;j<=m;j=j+i)
				a[j]=0;
		}
	}	
}
	
	printf("输出n和m中稍大数的质数列\n");
	for(i=0;i<k;i++)
	printf("%d ",b[i]);
	
	//接下来是求n的质因数
	int nn=n;
	k=0;
	while(nn!=1){
		if(nn%b[k]==0){
			nn=nn/b[k];
			c[b[k]]++;
		}
		else{
			k++;
		}
	} 
	printf("\n输出n的质因数\n");
	for(i=0;i<MAX;i++)
	if(c[i]!=0)
	printf("%d %d\n",i,c[i]);//c[]数组的下标i是n的质因数,c[i]的值是n对于下标i分解的次数,例如12对于2的分解次数是2 
	
	//接下来是求m的质因数
	int mm=m;
	k=0;
	while(mm!=1){
		if(mm%b[k]==0){
			mm=mm/b[k];
			d[b[k]]++;
		}
		else{
			k++;
		}
	} 
	printf("\n输出m的质因数\n");
	for(i=0;i<MAX;i++)
	if(d[i]!=0)
	printf("%d %d\n",i,d[i]);
	
	
	k=0;//找到n和m相同的质因数 以及 其最少的分解次数 
	for(i=0;i<MAX;i++){
			if((c[i]!=0)&&(d[i]!=0)){
			if(c[i]<=d[i])	e[i]=c[i];
			else e[i]=d[i];
			}
	}

		
	int end=1;//将相同的质因数也就是下标i取 最少次数e[i]的指数的所有结果相乘 
	for(i=0;i<MAX;i++){
	if(e[i]!=0){
		for(j=0;j<e[i];j++)
		end=end*i;
	}
	}
	printf("最大公约数为%d\n",end);
}

如果如图:

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 埃拉托色尼筛法是一种用于解质数的算法。它的基本思想是枚举每个正整数,并使用子将其中的合数过滤掉。 在调试埃拉托色尼筛法的代码时,首先应该检查每个步骤是否正确实现。这包括枚举每个正整数、使用子过滤合数、将剩余的数字存储在结果数组中。 如果在这些步骤中发现问题,可以使用调试器或打印语句来查看变量的值,以确定错误的原因。例如,可以打印每个数字是否被正确地枚举,或者检查子是否正确地过滤了合数。 另外,在调试代码时,还应注意检查边界条件是否正确。例如,在枚举数字时,应确保不会超过最大值,并且在使用子时,应确保不会尝试过滤小于 2 的数字。 此外,应注意检查代码的性能。埃拉托色尼筛法的时间复杂度为 O(n log log n),因此如果发现算法运行时间过长,可能需要对代码进行优化。 总之,调试埃拉托色尼筛法的代码需要仔细检查每个步 ### 回答2: 埃拉托色尼筛法是一种用于快速找出一定范围内所有素数的算法。以下是对这个算法的调试分析: 首先,埃拉托色尼筛法的核心思想是从小到大依次遍历每个数,将其所有的倍数标记为合数,剩下的未被标记的数就是素数。 在进行调试前,我们可以设定一个范围,比如找出区间[1, N]内所有的素数,其中N为通过输入确定的值。 在调试过程中,我们需要一个布尔数组来进行标记,长度为N+1,用来记录每个数是否为合数。初始时,将所有元素都标记为false,表示都是素数。然后我们从2开始遍历,将2倍、3倍、4倍...一直到N倍的数标记为合数(true)。这个过程中,我们只需要遍历到sqrt(N)即可,因为大于sqrt(N)的数的倍数已经在之前的遍历中被标记过了。 调试的关键是检查这个标记数组是否能得到正确的结果。我们可以准备一个预先定义好的素数列表,用来与算法得出的结果进行比对。对于每一个数,如果它是素数,则在标记数组中对应的位置应该是false;如果它不是素数,则在标记数组中对应的位置应该是true。 为了方便调试,我们可以在遍历过程中加入一些输出语句,例如输出当前遍历到的数,同时输出此时标记数组的具体情况。通过观察输出结果,可以判断标记数组是否正确。 此外,在编写代码时,还可以使用断点调试功能,逐步执行代码,查看每一步的输出结果,以便快速定位问题。 总结起来,调试埃拉托色尼筛法的关键在于检查标记数组的正确性,可以通过输出遍历到的数和标记数组的方式,或者使用断点调试等方法来辅助。 ### 回答3: 埃拉托色尼筛法是一种用于选质数的经典算法。它的基本思想是从2开始,将所有的倍数标记为合数,最后剩下的数就是质数。以下是对该算法进行调试分析的步骤和问题: 一、算法步骤: 1. 创建一个长度为n的布尔类型数组is_prime,初始化所有元素为true。 2. 从2开始依次遍历数组,如果当前数字is_prime[i]为true,则将其所有的倍数(is_prime[i]的倍数)标记为false。 3. 遍历结束后,返回is_prime中为true的索引值,即为所有的质数。 二、调试分析: 1. 首先,我们需要确定输入的n是否合法。即n是否大于等于2,如果小于2,则无可用质数,直接返回空。 2. 我们需要检查初始化数组is_prime的过程是否正确。即所有元素是否都被正确初始化为true。 3. 在遍历数组的过程中,需要判断当前数字是否为质数。我们可以检查当前数字是否已经被标记为合数,如果是则跳过。如果不是,则说明找到了一个质数,将其所有的倍数标记为合数。 4. 确保遍历结束后,返回的索引值是正确的质数数组。 三、可能遇到的问题: 1. 由于埃拉托色尼筛法的核心是通过标记倍数来选质数,所以在标记过程中可能出现数组越界的情况。我们需要确保标记倍数的索引值不超过数组的长度。 2. 算法的性能问题,当n很大时,选质数的时间复杂度可能较高。可以考虑使用其他优化方法来提高性能,如埃氏选法。 通过以上调试分析,我们可以更好地了解埃拉托色尼筛法的实现以及可能出现的问题,从而保证算法的正确性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值