关于数字的智力题-两个数之和与之积

题目:

已知两个1~30之间的数字,甲知道两数之和,乙知道两数之积。  
  甲问乙:"你知道是哪两个数吗?"乙说:"不知道";  
  乙问甲:"你知道是哪两个数吗?"甲说:"也不知道";  
  于是,乙说:"那我知道了";  
  随后甲也说:"那我也知道了";  
  这两个数是什么?

解答:

隐含条件:乙不知道答案,则说明这两个数之积不是素数。当甲回答说不知道答案后,乙马上知道了答案,说明乙能利用这一信息来排除掉一些选项,从而剩下唯一的选项。反过来,乙得出答案并告诉了甲后,甲亦能利用这一信息来排除一些选项,从而也剩下唯一的选项。

举例子:

假设这两个数是x,y。A=x+y;B=x*y。

站在乙方的角度,这时假设B=6,这能推出(1,6)和(2,3)两种组合。此时乙在这两个组合间犹豫不定时,甲告诉乙不知道答案。

假设答案是(1,6),则A=7。此时,甲手上的选项应该是(1,6),(2,5)和(3,4)。此时甲的确无法知道答案,因此(1,6)是候选答案。假设答案是(2,3),则A=5。此时,甲手上的选项是(1,4)和(2,3),因此甲也无法知道答案。这时,(2,3)也成为了候选答案。此种情况下出现了两个候选答案,因此乙到了最后还是无法得出答案。这与题设矛盾,一次可以排除这些组合。

假设,B=4.

站在乙方的角度,这时乙的选项是(1,4)和(2,2)。

假设答案是(1,4)。则A=5。分析如上。乙把(1,4)作为候选答案。假设答案是(2,2),则A=4。此时,甲手上的选项是(1,3)和(2,2)。因为(1,3)之积是素数,因此被排除。则乙告诉甲不知道答案的时候,甲应该能知道答案,而事实上甲不知道答案。因此(2,2)是不可能的。最后乙手上只剩下一个候选答案,因此他推出了答案。反过来,甲亦能根据此信息推出答案。因此(1,4)符合题设。

void BrainTester::ABOf1_30() {

	multimap<int, pair<int, int> > mid_result;
	for (int x = 1; x <= 30; ++x) {
		for (int y = x; y <= 30; ++y) {
			if (!this->isPrime(x * y)) {
				mid_result.insert(make_pair(x * y, make_pair(x, y)));
			}
		}
	}
	set<int> key_set;
	multimap<int, pair<int, int> >::iterator it;
	for (it = mid_result.begin(); it != mid_result.end(); ++it) {
		key_set.insert(it->first);
	}
	set<int>::iterator it_set;
	for (it_set = key_set.begin(); it_set != key_set.end(); ++it_set) {
		if (mid_result.count(*it_set) <= 1) {
			while ((it = mid_result.find(*it_set)) != mid_result.end())
				mid_result.erase(it);
		}
	}

	key_set.clear();
	//reset key_set
	for (it = mid_result.begin(); it != mid_result.end(); ++it) {
		key_set.insert(it->first);
	}

	multimap<int, pair<int, int> >::iterator beg;
	multimap<int, pair<int, int> >::iterator en;
	bool flag = false;
	multimap<int, pair<int, int> > result;
	for (it_set = key_set.begin(); it_set != key_set.end(); ++it_set) {
		beg = mid_result.equal_range(*it_set).first;
		en = mid_result.equal_range(*it_set).second;
		for (; beg != en; ++beg) {
			int x = beg->second.first;
			int y = beg->second.second;
			int sum = x + y;
			if (sum > 3) {
				int half = sum / 2;
				flag = false;
				for (int i = 1; i <= half; ++i) {
					if (mid_result.find(i * (sum - i)) != mid_result.end()) {
						if (flag) {
							result.insert(make_pair(x * y, make_pair(x, y)));
							break;
						} else {
							flag = true;
						}
					}
				}
			}
		}
	}
	key_set.clear();
	for (it = result.begin(); it != result.end(); ++it) {
		key_set.insert(it->first);
	}
	for (it_set = key_set.begin(); it_set != key_set.end(); ++it_set) {
		if (result.count(*it_set) != 1) {
			while ((it = result.find(*it_set)) != result.end())
				result.erase(it);
		}
	}
	for (it = result.begin(); it != result.end(); ++it) {
		cout << it->first << " (" << it->second.first << ","
				<< it->second.second << ")" << endl;
	}
}

  

关于数字的智力题-两个数之和与之积,布布扣,bubuko.com

时间: 2024-10-11 19:58:06

关于数字的智力题-两个数之和与之积的相关文章

关于数字的智力题-三个女儿的年龄

题目:一个经理有三个女儿,三个女儿的年龄加起来等于13,三个女儿的年龄乘起来等于经理自己的年龄,有一个下属已知道经理的年龄,但仍不能确定经理三个女儿的年龄,这时经理说只有一个女儿的头发是黑的,然后这个下属就知道了经理三个女儿的年龄.请问三个女儿的年龄分别是多少?为什么?解答:假设三个女儿按照年龄从小到大的排序时x,y,z.则1<=x,y,z<=11,x+y+z=13.能满足这两个条件的有很多组合,例如11(1,1,11),32(1,4,8)等.明显11(1,1,11)这些的组合是不符合实际情况

leetcode刷题--两数之和(简单)

一.序言 第一次刷leetcode的题,之前从来没有刷题然后去面试的概念,直到临近秋招,或许是秋招结束的时候才有这个意识,原来面试是需要刷题的,面试问的问题都是千篇一律的,只要刷够了题就差不多了,当然你的基础也要扎实,毕竟在技术面的时候很容易露馅的. 所以奉劝各位还未毕业,在大三或大二的师弟师妹早点刷题,心里也有底气进入求职大军,毕竟大四开始刷题的话时间上有些太紧了,推荐刷题的话就是牛客和leetcode. 回归正题,这次记录的是leetcode刷的第一题--两数之和. 二.审题 审题真的很重要

求两个数之和

求两个数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素. 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] int* twoSum(int* nums, int numsSize, int target, int*

【算法C++】检测数组里是否有两个数之和等于某个数

问题: 检测数组里是否有两个数之和等于某个数 解决方法一:先将数组排序,然后从两头开始遍历 数组排序后,从左端开始取最小值,从右端取最大值, 判断两者之和与目标的大小: 1. 等于时,输出两个数: 2. 大于时,右端移到第2个数,继续判断: 3. 小于时,左端移到第2个数,继续判断. #include <iostream> #include <string> #include <algorithm> using namespace std; void fun1(int

关于数字的智力题-小白鼠与毒药

题目: 有1000瓶药物,但是其中有一瓶是有毒的,小白鼠吃了一个星期以后就会死掉!请问,在一个星期内找出有毒的药物,最少需要多少只小白鼠? 解答: 用二进制的思路去思考,1000瓶药代表了1000种状态,那么1000用二进制表示可以用一个10位的二进制数就可以全部表示出来,考虑用十只白鼠来试验,用0和1代表它们最终的状态即死亡或活着,初始状态十只白鼠表示为0000000000. 关于数字的智力题-小白鼠与毒药,布布扣,bubuko.com

【C语言】不使用+-*/实现两个数之和

//不使用+-*/实现两个数之和 #include <stdio.h> int add(int num1, int num2) { int sum, car; do { sum = num1^num2; car = (num1&num2) >> 1; num1 = sum; num2 = car; } while (num2 != 0); return num1; } int main() { int a = 1; int b = 20; printf("%d\n

【c语言】求斐波那契数列的前40个数。特点,第1,2个数为1,从第三个数开始,该数是前面两个数之和

// 求斐波那契数列的前40个数.特点,第1,2个数为1,从第三个数开始,该数是前面两个数之和 #include <stdio.h> int main() { int a = 1; int b = 1; int c,i; printf("%d\t%d\t",a,b); for(i = 3; i <= 40; i++) { c = a + b; printf("%d\t",c); a = b; b = c; } printf("\n&quo

LeetCode算法题——两数之和(python)

两数之和: 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数.你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用.例如:给定 nums = [2, 7, 11, 15], target = 9.由nums[0] + nums[1] = 2 + 7 = 9,所以返回 [0, 1] 原文地址:http://blog.51cto.com/13921683/2318829

LeetCode刷题:第一题 两数之和

从今天开始刷LeetCode 第一题:两数之和 题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素. 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 代码如下: 1 /** 2 * Note: The retur