问题描述:
一天,鬼谷子随意从2-99中选取了两个数。他把这两个数的和告诉了庞涓,把这两个数
的乘积告诉了孙膑。但孙膑和庞涓彼此不知到对方得到的数。第二天,庞涓很有自信的
对孙膑说:虽然我不知到这两个数是什麽,但我知道你一定也不知道。随后,孙膑说:
那我知道了。庞涓说:那我也知道了。
解法:
假设鬼谷子给的两个数为x1,x2,庞涓为A(知道sum=x1+x2),孙膑为B(知道pro=x1*x2),本题当中最重要的三句话就是
① A说,我不知道,你也一定不知道
② B说,那我知道了
③ A说,那我也知道了
一句一句分析:
① =>
a. sum大于等于2+3=5,小于等于99+100=199的一个数(其实5和199也可以排除,因为如果和数是5或者199,就知道是哪两个数相加了);
b. pro不能等于一些特定的数,例如6,因为如果是6就知道肯定是2和3相乘得来的。这类数字的特点是只能由一组2至100范围内的数相乘得来。此处用一个函数来判断(isBknow(int x)),B是否能判断出x是由哪两个数相乘,若能返回1,不能则返回0。
实现方法:for循环(5<sum<199),判断每一组满足和数为sum的x1与x2的积是否满足条件b的要求,要求每一组都应该满足b的要求,否则A无法确定B一定不知道。例如当sum=7时,满足和数的6的x1,x2组合有2+5,3+4,对应的积为2*5=10,3*4=12,10不满足条件b,12满足条件b,所以sum=7不符合题目要求。求出所有符合题目要求的sum,存在数组sumArray[]里;
② =>
a. B看自己手中的数pro,有很多种相乘的可能,若x1+x2的值与数组sumArray[]中的某个值相等,则B就可以知道是哪两个数相乘了。并且要求只能与sumArray[]中某一个值相等,因为若有多组数的和都存在于sumArray[]中,则B还是不能确定是哪两个数相乘。
③ =>
a. 满足x1+x2= sumArray[i]的x1,x2有好几组,于是就有很多对应的积,只能有一个积满足②中的条件。
代码分析:
(1)B是否能判断出x是由哪两个数相乘,即若x只能由一组数相乘得来,那么B可以判断出,返回1,若不能,返回0
publicstatic int isBknow(int x){
inttag=0; //找到0对乘数与被乘数
for(inti=low;(tag<2)&&(i<=java.lang.Math.sqrt(x));i++){ //鬼谷子给的范围是(low,high)
if((x%i==0)&&(x/i<=high))tag++; //找到1对乘积的x的组合
}
if(tag==2)return 0; //若不止一对则B无法判断出是哪两个数相乘
elsereturn 1;
}
(2)求出满足①的数组sumArray
for(intsum=2*low+1;sum<=(2*high-1);sum++){ //庞涓说的第一句话:虽然我不知道这两个数是多少 但我肯定你也不知道
inttag=0;
intstart;
if(sum<=low+high)start=low;
elsestart=sum-high; //要求两个加数都在2到100的范围内
for(inti=start;(i<=sum/2)&&(tag==0);i++){
intj=sum-i;
if(isBknow(i*j)==1){
tag=1;
}
}
if(tag==0){
sumArray[k]=sum;
k++;
}
}
(3)满足条件②③
for(int i=0;i<k;i++){
intstart;
intcount1 = 0; //一共有几种组合,使得和为sumArray[i]
intcount2 = 0;
intproResult=0; //B手上的积pro
intx1=0,x2=0; //鬼谷子的两个数
if(sumArray[i]<=low+high)start=low;
elsestart=sumArray[i]-high; //要求两个数大于等于2小于等于100
for(intj=start;j<=sumArray[i]/2;j++){
intpro=j*(sumArray[i]-j);
intflag=1;
for(intz=low; (z<=java.lang.Math.sqrt(pro))&&(flag==1); z++){
if((pro%z==0)&&(z!=j)){
inttemp=z+pro/z;
if(isInArray(sumArray,temp)==1){ //一旦在数组里,则表示B不能判断出是哪两个数相乘
flag=0; //跳出循环
count2++;
}
}
}
if(flag==1){
proResult=pro;
x1=j;
}
count1++;
}
if(count2==count1-1){
x2=sumArray[i]-x1;
System.out.println("和为"+sumArray[i]+"积为"+proResult+"; 鬼谷子给的两个数是:"+x1+","+x2);
}
}
待改进处:算法写的太复杂了,有没有更简单的方法。