烧脑奇怪数-救救孩子

TTL? 2019-10-30 02:49:28
奇怪数为这样一个整数,①:除了自身以外所有因子之和大于这个数本身(首先必须是盈数);②:除了自身以外所有因子的集合,没有任何一个子集中所有数的和等于这个数本身,例如70就是一个奇怪数,求1000以内的第二个奇怪数 举报
...全文
1319 44 打赏 收藏 转发到动态 举报
写回复
用AI写文章
44 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wayward:) 2019-11-16
  • 打赏
  • 举报
回复
上面已经有人用回溯法求解了子集,但是如果子集里面个数不是很多的话,是可以暴力用二进制来表示子集的。 [子集生成 递归回溯](https://blog.csdn.net/Africa_South/article/details/102612501) long long 限制子集个数在63以内

#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long LL;
int factor[1010]; // 因子
int sum, cnt; // 因子的和,因子的个数
int subset; // 子集和,可以用sum代替
bool isYingshu(int num) {
	// 拆分一个数num,然后因子存入factor[],并返回是不是盈数
	cnt = 0, sum = 0;
	factor[cnt++] = 1; sum += 1; // 1 肯定是因子
	for (int i = 2; i*i <= num; i++) {
		if (num % i == 0) {
			factor[cnt++] = i; sum += i;
			factor[cnt++] = num / i; sum += (num / i);
			if (i*i == num) { // 多算了一个
				cnt--; sum -= i;
			}
		}
	}
	if (sum <= num) return false;
	else return true;
}

bool isStrange(int num) {
	// 返回是不是奇怪数
	if (!isYingshu(num)) return false;
	LL len = ((LL)1 << cnt); // 总共的子集情况
	for (LL i = 0; i < len; i++) {
		subset = 0;
		for (LL j = 0; j < cnt; j++) {
			if (i & ((LL)1 << j)) subset += factor[j];
		}
		if (subset == num) return false;
	}
	return true;
}

int main() {
	for (int i = 70; i <= 1000; i++) {
		if (isStrange(i)) {
			printf("该数%d,因子个数%d\n", i,cnt);
		}
	}
	return 0;
}
  • 打赏
  • 举报
回复
#include <iostream> #include<stdio.h>  #include<stdlib.h> #include<math.h> #define  MAX  50 int back(int i, int s, int n); int static t; int i, j, n, k, sum=0, a[MAX], num; int flag = 1; int b[MAX] = { 0 };  //初始化数组b,给定数组a中的元素一个状态,类似排列组合  int main() { for (n =4; n <= 4; n++) { int i = 0,  num = 0; for (j = 2; j <= n - 1; j++) //找 n的所有因子  { if (n % j == 0) { a[i] = j;    //将n的因子存在数组a[1000]中  sum = sum + j;// 计算所有因子的和  i++;     //数组的序号+1  num++; //计算数组的大小,n的所有因子数  } } if(sum!=0){} sum = sum + 1;  //1也是n的因子  a[num] = 1;  //把1赋给数组a[1000]  if (sum > n)  //判断n是否为赢数  { t = num + 1;    back(1, t, n);//把n的因子数赋给t  if (flag)//第1个元素开始 ,求n所有因子的子集的和并与sum比较 printf("%d是奇怪数", n); break;//找到第一个奇怪数后停止循环   } } return 0; } int back(int i, int s, int n) { int k, Sum = 0; if (i > s)//判断a中的元素的状态是否都已确定  { for (k = 1; k <= s; k++)// 对a中的元素 进行排列组合  { if (b[k])    //判断第K个元素的状态 { if (a[k] != 0) {  Sum += a[k]; } } } if (n == Sum) flag = 0; return flag;//如果满足这个条件,就不用执行后面为a中的元素赋予一种状态的操作 } { b[i] = 1;                //对a中元素的状态进行排列组合  back(i + 1, t, n); b[i] = 0; back(i + 1, t, n); return flag; } }
  • 打赏
  • 举报
回复
这个好高深啊,弄不懂
fenda307 2019-11-04
  • 打赏
  • 举报
回复
奇怪数为这样一个整数,①:除了自身以外所有因子之和大于这个数本身(首先必须是盈数);②:除了自身以外所有因子的集合,没有任何一个子集中所有数的和等于这个数本身,例如70就是一个奇怪数,求1000以内的第二个奇怪数

好难呀
  • 打赏
  • 举报
回复
10000以内7个数:
70
836
4030
5830
7192
7912
9272
tommy198307 2019-11-03
  • 打赏
  • 举报
回复
数学就是那么深奥真正有用 的地方很少。我们要学会有的放矢的学习
ericwongpm 2019-11-03
  • 打赏
  • 举报
回复
兄弟 ,这行代码是你自己写。
小胡同的诗 2019-11-02
  • 打赏
  • 举报
回复
除了暴力外筛法+分解定理也可做,打一张1000内的表,再维护2张不符合两个条件的表分别筛一下
TWxbnz 2019-11-01
  • 打赏
  • 举报
回复
什么意思?没用看懂哈哈
TTL? 2019-10-31
  • 打赏
  • 举报
回复
打错了不好意思正确答案836
TTL? 2019-10-31
  • 打赏
  • 举报
回复
答案不正确,正确答案是839
qq_38446291 2019-10-31
  • 打赏
  • 举报
回复
这真的能运行出正确结果吗
TTL? 2019-10-31
  • 打赏
  • 举报
回复
引用 36 楼 wowpH的回复:
memset初始化数组为0。 刚试了一下。这句代码是多余的。可以删掉。 我习惯清零了,所以就写了。
谢谢大佬,后面用回溯法求子集的还是不懂,我再仔细看看,非常感谢您
TTL? 2019-10-31
  • 打赏
  • 举报
回复
兄弟这程序运行结果不对
wowpH 2019-10-31
  • 打赏
  • 举报
回复
memset初始化数组为0。 刚试了一下。这句代码是多余的。可以删掉。 我习惯清零了,所以就写了。
TTL? 2019-10-31
  • 打赏
  • 举报
回复
引用 32 楼 wowpH的回复:
好了,改对了。
// wowpH
// 2019年10月31日10:10:03
#include <stdio.h>
#include <math.h>
#include <string.h>

#define TRUE 1
#define FALSE 0
#define MAX_NUM 1000

int strangeNumber(int);// 判断是否是奇怪数

int sum;// 因子的和
int factor[MAX_NUM];// 保存因子
int factorNum;// 因子个数
int abundantNumber(int);// 判断是否是盈数

int back(int, int);// 回溯判断是否有子集的和是num

int main(void) {
	for (int i = 71; i <= 1000; ++i) {
		if (TRUE == strangeNumber(i)) {
			printf("%d\n", i);
			break;
		}
	}
	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) {
	// 初始化
	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;
}
但是menset是干什么的函数呢
TTL? 2019-10-31
  • 打赏
  • 举报
回复
还有这这能运行出来不😂😂我急用
TTL? 2019-10-31
  • 打赏
  • 举报
回复
兄弟,你这是用啥写的,粘贴到c++上一篇红色
TTL? 2019-10-31
  • 打赏
  • 举报
回复
谢谢大哥,小女子无以为报,只能表达对您的景仰与感谢
wowpH 2019-10-31
  • 打赏
  • 举报
回复
我发现搜不到这个题目的博客。所以整理成博客了,不迷路,哈哈哈哈:https://blog.csdn.net/pfdvnah/article/details/102832648
加载更多回复(24)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧