提示:
代码存在问题,这里找出 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是一个合数,求出此合数最多由多少个最小不同质数和组成,
并按要求从小到大输出这些质数
关键合数最多由多少个最小不同质数和组成
分析
- 先找出2008以内的所有质数存入数组a中
- 从0开始扫描数组a相加和为sum,直到值大于或者等于2008,肯定大于(吐槽,不然那简单了)
- 计算出sum与2008的差值d,然后从大到小扫描数组a寻找差值d的替代值(即它本身等于差值,或者它本身大于差值,但是下一个值小于差值)
- 重复步骤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]);
}
}
}
}