(烧脑)奇怪数 - C语言 - 回溯

mac2024-03-21  26

文章目录

一、题目二、分析思路三、C语言代码四、相关链接

回复此贴:https://bbs.csdn.net/topics/394896625

一、题目

奇怪数为这样一个整数 @wowpH ①:除了自身以外所有因子之和大于这个数本身(首先必须是盈数) ②:除了自身以外所有因子的集合,没有任何一个子集中所有数的和等于这个数本身

例如:70就是一个奇怪数,求1000以内的第二个奇怪数 70的除自身外的因子有:1,2,5,7,10,14,35。 它们的和为:74 > 70,所以70是盈数。 不存在一个子集的和为70(或4),所以它是奇怪数。


二、分析思路

核心部分分两个函数:一个用于判断是否是盈数,一个用于判断是否存在子集和为自身。@pfdvnah

1、用数组保存所有除自身外的因子 2、for 循环查找所有因子。循环到平方根即可。一趟循环可以找出两个因子。 3、注意,如果数自身是平方数,那么循环里面就多加了一次。循环后面要减掉。 4、是盈数返回 1,不是返回 0

子集和通过回溯计算。更好的是 DP 实现,怕新手看不懂,所以直接用回溯解决。实际上思路差不多。 每个数有两种状态,加到子集中,不加到子集中。@wowpH 不断地这样选择,直到所有数都选择完后,看看还剩余多少,剩的刚好为 0 的话,说明有子集的和为 num,即不是奇怪数。


三、C语言代码

/***************************************************************** 功能:计算并输出区间[LFET,RIGHT]中所有的奇怪数 作者:wowpH pfdvnah 日期:2019年10月31日10:10:03 链接:https://blog.csdn.net/pfdvnah/article/details/102832648 *****************************************************************/ #include <stdio.h> #include <math.h> #include <string.h> #define TRUE 1 #define FALSE 0 #define MAX_FACTOR_NUM 1000 #define LEFT 71 #define RIGHT 1000 int strangeNumber(int);// 判断是否是奇怪数 int sum;// 因子的和 int factor[MAX_FACTOR_NUM];// 保存因子 int factorNum;// 因子个数。@wowpH int abundantNumber(int);// 判断是否是盈数 int back(int, int);// 回溯判断是否有子集的和是num int main(void) { for (int i = LEFT; i <= RIGHT; ++i) { if (TRUE == strangeNumber(i)) { printf("%d\n", i); } } return 0; } int strangeNumber(int num) { if (FALSE == abundantNumber(num)) { return FALSE;// 不是盈数,即不是奇怪数 } if (FALSE == back(0, num)) { return FALSE;// 存在子集的和为num,即不是奇怪数 } return TRUE; } int abundantNumber(int num) { // 初始化。@pfdvnah memset(factor, 0, sizeof(factor)); factorNum = 0; factor[factorNum++] = 1;// 1肯定是因子 sum = 1; int max = (int)sqrt(num); // 循环找到num的所有因子 for (int i = 2; i <= max; ++i) { if (0 == num % i) { factor[factorNum++] = i; factor[factorNum++] = num / i; sum += i + num / i; } } // num是开方数,那么循环里面max加了两遍,要减掉多余的 if (max * max == num) { --factorNum; sum -= max; } return sum <= num ? FALSE : TRUE; } int back(int index, int left) { if (index >= factorNum) { return 0 == left ? FALSE : TRUE; } if (FALSE == back(index + 1, left)) {// 不选择第index个数 return FALSE; } // 选择第index个数,剩余的减去当前数 if (FALSE == back(index + 1, left - factor[index])) { return FALSE; } return TRUE; }

四、相关链接

题目来源:https://bbs.csdn.net/topics/394896625 原文链接:https://blog.csdn.net/pfdvnah/article/details/102832648 盈数_百度百科:https://baike.baidu.com/item/%E7%9B%88%E6%95%B0/2567294?fr=aladdin


- End - wowpH - pfdvnah -
最新回复(0)