鬼谷子问徒

意义深远的题:
孙膑,庞涓都是鬼谷子的徒弟。一天鬼谷子出了这道题目:
他从2到99中选出两个不同的整数,把积告诉孙,把和告诉庞;
庞说:我虽然不能确定这两个数是什么,但是我肯定你也不知道这两个数是什么。
孙说:我本来的确不知道,但是听你这么一说,我现在能够确定这两个数字了。
庞说:既然你这么说,我现在也知道这两个数字是什么了。
请问这两个数字是什么?为什么?
一开始看这道题真的令人震惊。。。。
还有这种操作的嘛
分析一下吧
选两个数A,B
假定A小于B
判断一下范围
A+B 在[5,197]之间
A * B [6,98*97] 之间

1、庞涓能确定孙膑肯定不知道这两个数

推论1:A与B不能均为质数 why? 这样的话A*B可以做唯一分解,而两个人一开始都是没法直接根据自己手中的数得出结论的

推论2:庞涓的和数一定不能拆成两个质数之和,否则孙膑拿到的积可能拆成唯一一种两个质数之积的情况,此时孙膑就可以猜出这两个数,庞涓不能排除这种可能性,就不会有确信。
根据哥德巴赫猜想,偶数全都不可以成为庞手中的数
歌德巴赫猜想认为任意大于4的偶数都能被拆成两个奇质数之和

推论3:庞涓的和数一定不是大于55的数。因为大于53的数始终能够拆成质数53和另一个大于2的数,在2-99的限制下,这两个数的乘积只有这唯一一种拆分方法。举例:如果庞涓手上的和数是57,可以拆成53+4,当孙膑拿到212这个积,只有453这一种拆分可能性,因为2106的另一种拆分方法导致有一个数超过99。由此排除55以上的所有数

code:

#include <bits/stdc++.h>
using namespace std;
int prime(int n){
	if(n==2) return 1;
	int q=sqrt(n);
	for(int i=2;i<=q;i++){
		if(n%i==0) return 0;
	}
	return 1;
}
int main(){
	int k;
	cin>>k;//最大为k 本例为99
	k/=2;//取一半
	while(!prime(k)){
		k++;//找最近的素数
	}
	for(int i=5;i<=k;i++){
		if(i%2==0) continue;//偶数不考虑
		int ok=1;
		for(int j=2;j<=i/2;j++){//A<B
			if(prime(j)&&prime(i-j)){//可以分解成素数
				ok=0;//不ok
				break;	
			} 
			// printf("sum=%d %d %d\n",i,j,i-j );
		}
		if(ok){
			printf("sum=%d\n",i);
		}
	}
	return 0;
}

这里写图片描述
2.孙膑知道自己手中的积,并说本来不知道,但现在知道了。
意味着,孙膑看了自己手上的积后,分解因式对应的所有拆分情况中有且仅有一种,两个因数的和是以上11个数中的一个。

举例:当庞涓看到两个数的和是11时,孙膑看到两数的积只能是18(29)、24(38)或者28(47),但不能是30(56)。因为如果是30,可以拆成215、310和56三种情况,其中215和5*6两种情况下,由于2+15=17和5+6=11都在以上11个数内,所以满足庞涓说出第一句话的要求,但孙膑不能确定鬼谷子的两个数是2和15,还是5和6,所以不会说出他已经知道这两个数的话。回头再看积是18的情况,孙膑可以猜到鬼谷子的两个数是2和9或者3和6,但因为3+6=9不在以上11个数内,不满足庞涓说出第一句话的条件,所以不可能,于是只有2和9唯一一种可能。同理,积是24和28的情况都可以类似推理。

code:update!

#include <bits/stdc++.h>
using namespace std;
int prime(int n){
	if(n==2) return 1;
	int q=sqrt(n);
	for(int i=2;i<=q;i++){
		if(n%i==0) return 0;
	}
	return 1;
}
vector<int> v;
int ans[10050];
int check(int a,int b){
	int mul=a*b;
	int q=sqrt(mul);
	int cnt=0;
	for(int i=2;i<=q;i++){
		if(mul%i==0){
			if(ans[i+mul/i]) cnt++;
		}
	}
	return cnt;
}
int main(){
	int k;
	cin>>k;//最大为k 本例为99
	k/=2;//取一半
	while(!prime(k)){
		k++;//找最近的素数
	}
	for(int i=5;i<=k;i++){
		if(i%2==0) continue;//偶数不考虑
		int ok=1;
		for(int j=2;j<=i/2;j++){//A<B
			if(prime(j)&&prime(i-j)){//可以分解成素数
				ok=0;//不ok
				break;	
			} 
			// printf("sum=%d %d %d\n",i,j,i-j );
		}
		if(ok){
			ans[i]++;
			v.push_back(i);
			printf("sum=%d\n",i);
		}
	}
	for(int i=0;i<v.size();i++){//遍历vector
		int flag=0;
		for(int j=2;j<=v[i]/2;j++){
			if(check(j,v[i]-j)==1){
				flag++;
				if(flag==1)printf("%d: ",v[i]);
				printf("(%d,%d) ",j,v[i]-j );
			}  		
		}
		printf("\n");
	}
	return 0;
}

这里写图片描述

3、庞涓是知道自己手中的和数,当孙膑猜出两个数后,庞涓也知道了这两个数字,由于庞涓并不知道两数积,所以只能从以上表格出发确定,这就要求第二步有唯一解。
即4,13

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值