相约2008:2008是一个合数,求出此合数最多由多少个最小不同质数和组成, 并按要求从小到大输出这些质数

69 篇文章 319 订阅 ¥39.90 ¥99.00

提示

代码存在问题,这里找出 2008 最多由多少个不同的质数和组成,原先的思路是从最小开始入数组,直到总和大于2008,然后开始剔除,但是这种方法不对

这里为了方便考虑,可以试着将 2008 替换为 16,这样好计算和考虑(2,3,5,7,11,13),按原先的思路是选到了(2,3,5,7),结果是17比原先大1,试着用上 7 的后一位11,来替代已经找到(2,3,5,7)中的两位,使应该剔除的这两位为12比如5,7,但是也挺麻烦。

另外的想法是,虽然考虑从最小入手,直到总和大16不对,但是却可以确定该质数和最多由多少位组成,比如原先思路(2,3,5,7)总和比 16 大1,就可以确定,该质数和最多 3位,不可能是4位,因为最小的四位已经大于它了。这样其实就相当与组合数了即从6位数字中任取3位是否能达到质数和位 16 的要求,不行就2位,以此类推,也挺麻烦。

这些是我的想法,感觉这里应该用回溯法来尝试所有可能,目前没有很好地思路,如果哪位大神有好的思路想法,欢迎提出来一起讨论学习

基础知识

合数指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。与之相对的是质数,而1既不属于质数也不属于合数。最小的合数是4。其中,完全数与相亲数是以它为基础的。

注意

由于记录需要剔除的值的数组b,记录的值是从大到小,因此和最后数组a输出的值进行比较时应该注意

		for(j=0; j<=i; j++) {
//			由于在b中存放的需要剔除的值是由大到小排列的因此应使用n--来控制b[k]的值
			if(a[j]==b[k-1]) {
				printf("%d剔除\n",a[j]);
				k--;
			} else printf("%d\n",a[j]);
		}

题目

相约2008:2008是一个合数,求出此合数最多由多少个最小不同质数和组成,
并按要求从小到大输出这些质数

关键合数最多由多少个最小不同质数和组成

分析

  1. 先找出2008以内的所有质数存入数组a中
  2. 从0开始扫描数组a相加和为sum,直到值大于或者等于2008,肯定大于(吐槽,不然那简单了)
  3. 计算出sum与2008的差值d,然后从大到小扫描数组a寻找差值d的替代值(即它本身等于差值,或者它本身大于差值,但是下一个值小于差值)
  4. 重复步骤3直到差值为零

代码(有问题)

#include <stdio.h>
#include <math.h>
#define max 2008
int main() {
//	数组a记录0-2008内的质数,数组b记录需要剔除的值
	int a[max],b[max];
	int i,j,k=0,flag,sum=0,d;

	//使用a[k]来记录2-2008之间的素数
	for(i=2; i<=2008; i++) {
		flag = 1;
		for(j=2; j<=sqrt(i); j++) {
			if(i%j==0)	flag = 0;
		}
		if(flag)	a[k++] = i;
	}

//	计算质数的sum和
	for(i=0; i<k; i++) {
		sum = sum+a[i];
//		当sum大于或等于2008时跳出循环
		if(sum>=2008) {
			break;
		}
	}

//	如果sum为2008,满足题目要求输出
	if(sum==2008) {
		for(j=0; j<=i; j++)	printf("%d\n",a[j]);
	}

//	当sum大于2008时,关键是a[i]这个值,过大,因此需要将sum-2008的差值使用最大的质数和代替
	else {
		printf("此时sum为:%d,比2008大:%d\n",sum,sum-2008);
//		使用前i个值,将差值d逐步化为0,也就是使用将和为d的质数从前i个里面剔除
		d = sum-2008;k=0;
		//根据题目要求从大到小扫描 
		for(j=i; j>=0&&d!=0; j--) {
//				如果当前的i值是小于d的最大质数或者等于d则将其记录
			if((a[j]<d&&a[j+1]>d)||d==a[j]) {
				d = d - a[j];
				b[k++] = a[j];
			}
		}

		for(j=0; j<=i; j++) {
//			由于在b中存放的需要剔除的值是由大到小排列的因此应使用n--来控制b[k]的值
			if(a[j]==b[k-1]) {
				printf("%d剔除\n",a[j]);
				k--;
			} else printf("%d\n",a[j]);
		}
	}
	return 0;
}

计算2006的合数,代码写的个别地方不一样(两次写的时间不同)–存在问题

# include "stdio.h"
# include "math.h"
#define max 2006
void main() {
	int a[max],b[max];
	int i,j,temp,k=0,flag,sum;
	for(i=1; i<=2006; i++) {
		temp = sqrt(i);
		flag = 1;
		for(j=2; j<=temp; j++)
			if(i%j==0) {
				flag =0;
				break;
			}
		if(flag)	a[k++] = i;
	}
	
	i = sum = k = 0;
	while(sum<2006) {
		sum = sum+a[i];
		i++;
	}

	if(sum==2006) {
		for(j=0; j<i; j++)	printf("%d\n",a[j]);
	} else {
		temp = sum-2006;
		for(j=i-1; j>0&&temp!=0; j--) {
			if(a[j]>temp&&a[j-1]<=temp) {
				temp = temp - a[j-1];
				b[k++] = a[j-1];
			}
		}
		k=k-1;
		sum=0;
		for(j=0; j<i; j++) {
			if(a[j]==b[k]) {
				printf("%d被剔除!!!\n",a[j]);
				k--;
			} else {
				sum = sum + a[j];
				printf("sum=%d--%d\n",sum,a[j]);
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南淮北安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值