問題描述:
一天,鬼谷子隨意從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);
}
}
待改進處:演算法寫的太複雜了,有沒有更簡單的方法。
下載代碼