**********
趣味思考题:请通过编程求解如下孙膑和庞涓问题。
庞涓拿到两个整数(这个整数均在2到99之间)之和,孙膑拿到这两个整数之积。下面是一段很有趣的对话。
庞涓说:我不知道这两个整数是多少,但我肯定你也不知道。
孙膑说:我本来不知道这两个数是多少。但既然你这么说,那我现在知道了。
庞涓说:哦,那我也知道了。
要求输出所有可能的结果,包括这两个整数、这两个整数之和以及这两个整数之积。
**********
会的大哥大姐们帮忙解决一下,thanks....

解决方案 »

  1.   

    强人出手?我的方法是:
    public getAllInfor(int a, int b){
        for(int i=2;i<100;i++){
           for(int j=2;j<100;j++){
             Systen.out.prtintln("====================");
             Systen.out.prtintln("第一个数:"+i);
             Systen.out.prtintln(("第二个数:"+j);
             Systen.out.prtintln("和:"+(i+j));
             Systen.out.prtintln("成绩:+(i*j)");
           }
        }}
    ^_^ 最笨的方法
      

  2.   

    程序好写,但是问题难想,因为孙膑已开始不知道这两个数,所以这两个数不可能同时是质数,而庞涓可以根据自己手里的两个数的和判断出这一点,所以我的思路是首先找出所有的质数,取得这些指数的和根积,然后循环所有的数字,抛出和 或者 积 跟这些得到的和或积相等的两个整数,将剩下的打印出来,本来以为最后肯定只剩一组数据,结果小弟列出了1953种组合;看样子,还有什么地方没有注意,小弟,姑且抛砖引玉了,期待后面的大虾给出完善的思想
    //打印出可能的组合数
    one is : 98the other is : 99the sum  is : 197the ji  is : 9702the lenth  is : 1953public static void printAvaible() {    ArrayList sushuArray = getSuShu(99);
        ArrayList heArray = new ArrayList();
        ArrayList jiArray = new ArrayList();
        int size = sushuArray.size();
        for (int i = 0; i < size; i++) {
          int a = ( (Integer) sushuArray.get(i)).intValue();
          for (int j = i + 1; j < size; j++) {
            int b = ( (Integer) sushuArray.get(j)).intValue();
            int he = a + b;
            int ji = a * b;
            heArray.add(new Integer(he));
            jiArray.add(new Integer(ji));
          }
        }
        int length = 1;
        for (int i = 2; i < 100; i++) {
          for (int j = i + 1; j < 100; j++) {        int he = i + j;
            int ji = i * j;
            if (!heArray.contains(new Integer(he)) &&
                !jiArray.contains(new Integer(ji))) {          System.out.println("one is : " + i);
              System.out.println("the other is : " + j);
              System.out.println("the sum  is : " + he);
              System.out.println("the ji  is : " + ji);
              System.out.println("the lenth  is : " + (length++));
              
            }
          }
        } //这两个数字不可能同时是素数,如果同时使素数的话,孙膑马上就可以知道
        //也就是说庞涓根据自己手里的和就可以判断出来
        //找出全部的素数,获取他们的和,积
      }  //返回所有的素数
      public static  ArrayList getSuShu(int lenth) {
        ArrayList allArray = new ArrayList();
        ArrayList lostArray = new ArrayList();    for (int i = 2; i <= lenth; i++) {
          allArray.add(new Integer(i));
          for (int j = 2; j < i; j++) {
            if (i % j == 0) {
              lostArray.add(new Integer(i));
              break;
            }
          }
        }
        for (int i = 0; i < lostArray.size(); i++) {
          Integer a = (Integer) lostArray.get(i);
          allArray.remove(a);
        }
        return allArray;  }
      

  3.   

    转一下,:
    方便描述,假设:有2到99间两数a、b,A知道和s,B知道积m
    由A的第一句话就可以推得,两数和必然小于55
    原因:如果s=a+b>=55,则s一定可以写为s=c+d,其中53<=c<=97,是素数,2<=d<=99。这样,假如恰好a取c、b取d,那么m=c*d=a*b是一个可唯一乘积分解的数,也就是说B有可能只知道积就可以猜出来。
    那么A说你一定猜不出就不准确了,所以s<55由A的第一句话还可以推得,这两个数不能写为两个素数的积。因此,根据哥德巴赫猜想“每一个大于或等于6的偶数都可表示成两个奇素数之和”,推得至少在2~200范围内,s不能是偶数所以s的取值范围目前可以确定为[5,54]间的奇数,还可以进一步缩小范围。对奇素数p,3<=p<=53,p+2是s肯定取不到的数,因为如果取到了,存在2+p的分解使它们的积唯一。这样s可能的取值范围就是 {11,17,23,27,29,35,37,41,47,51,53}s是奇数,说明a,b必然一个为奇一个为偶(不妨a奇b偶)。因此m=a*b为偶数再分析B的第一句话。因为仅仅上面的条件就可以在知道m的条件下,而推出a,b。所以m=a*b的奇偶分解必然是唯一的。这说明奇数a必然是素数,b=2^n再看A的的二句话。同样,仅仅上面的条件,就能确定s,说明s形如奇素数加一个2^n的偶数的分解也是唯一的。根据上面的几条判据,对{11,17,23,27,29,35,37,41,47,51,53}进行筛选,同时注意s的a+b分解唯一性,可以很快得到结果
    例如:11=4+7=8+3,不唯一
    23=16+7=4+19,不唯一最终得到s=17,a=13,b=4,m=52 
      

  4.   

    借鉴一下
    public static getAllInfor(int a, int b){
        for(int i=2;i<100;i++){
           for(int j=2;j<100;j++){
             System.out.println("====================");
             System.out.println("第一个数:"+i);
             System.out.println(("第二个数:"+j));
             System.out.println("和:"+(i+j));
             System.out.println("成绩:"+(i*j));
           }
        }

    }
      

  5.   

    public static void main(String[] args) {
        for(int i=2;i<100;i++){
           for(int j=2;j<100;j++){
             System.out.println("====================");
             System.out.println("第一个数:"+i);
             System.out.println(("第二个数:"+j));
             System.out.println("和:"+(i+j));
             System.out.println("成绩:"+(i*j));
           }
        }
                                  } }
      

  6.   

    “原因:如果s=a+b>=55,则s一定可以写为s=c+d,其中53<=c<=97,是素数,2<=d<=99。这样,假如恰好a取c、b取d,那么m=c*d=a*b是一个可唯一乘积分解的数,也就是说B有可能只知道积就可以猜出来。
    那么A说你一定猜不出就不准确了,所以s<55
    ”实在是难以理解,没办法,大学数学,全部还给老师了。请教一下猪猪,如果积为1890,和为97(两数为27,70);或者积为1890,和为93(30,63)的话,又有哪里不符合题目要求呢?
      

  7.   

    vulner(猪猪)的思路太数学了,我看了很久,还不是很明白。
    下面是我作为一个程序员的思路,我觉得简单很多。假设:和为s,积为p,两个整数为a和b,其中s=a+b, p=a*b,称其为一对第1步:我不知道这两个整数是多少,但我肯定你也不知道。
    这说明:
    1、我不知道:s至少是两对整数的和,如果仅有一对的话,即a+b=s,那么“我”就知道这两个数是什么了,如5。
    2、我肯定你也不知道:对于所有相加等于s的两个整数,他们的乘积p,至少有两对整数的乘积与p相等,同上,如果只有一对整数的乘积等于p,那么“你”就肯定知道这两个数了。
    换句话说,这两个数不能都是质数
    对于和为s的所有整数对,都要满足2,这就是“我肯定”的意思,因为只要有一对全部都是质数的话,“我”就不能“肯定”了。
    所以,找到和为s,积为p,但不同时为质数的所有整数对
    结果:和为11,17,23,27,29,35,37,41,47,51,53的整数满足条件
    第2步:我本来不知道这两个数是多少。但既然你这么说,那我现在知道了。
    这说明:
    1、对于乘积为p的所有整数对,至少有一对他们的和是第1步结果之一
    2、“我现在知道”说明对于乘积为p的整数对中,只有一对的和是第1步结果之一,如果不止一对的话,“我”还是不能确定。
    所以:对于第1步结果中所有可能的整数对,相乘得到p,再统计所有乘积为p的整数对的和在第1步结果中出现的次数,出现次数为1的即为结果。
    结果:整数对为4,13,他们和是s=17,他们的乘积为p=52
    “那我也知道了”是废话。还有不明白的提出来,继续讨论。
    程序见下
      

  8.   

    import java.util.*;public class FindOut { static int MIN = 2;
    static int MAX = 99;
        static boolean[] available = new boolean[(MAX+MIN+1) * 2]; public static void main(String[] args) { // 假设:和为s,积为p,两个整数为a和b,其中s=a+b, p=a*b,称其为一对 // 第1步:我不知道这两个整数是多少,但我肯定你也不知道。
    // 这说明:
    // 1、我不知道:s至少是两对整数的和,如果仅有一对的话,即a+b=s,那么“我”就知道这两个数是什么了,如5。
    // 2、我肯定你也不知道:对于所有相加等于s的两个整数,他们的乘积p,至少有两对整数的乘积与p相等,同上,如果只有一对整数的乘积等于p,那么“你”就肯定知道这两个数了。
    // 换句话说,这两个数不能都是质数
    // 对于和为s的所有整数对,都要满足2,这就是“我肯定”的意思,因为只要有一对全部都是质数的话,“我”就不能“肯定”了。
    // 所以,找到和为s,积为p,但不同时为质数的所有整数对
    // 结果:和为11,17,23,27,29,35,37,41,47,51,53的整数满足条件
    loop1: for (int s=MIN*2; s<=MAX*2; s++) {
    available[s]  = false;
    Vector<IntPair> v = getAddFactors(s);
    int len = v.size();
    if (len < 2) {
    continue loop1;
    }
    for (int i=0; i<len; i++) {
    IntPair ip = v.get(i);
    if (isPrimePair(ip)) {
    continue loop1;
    }
    }
    available[s]  = true;
    } // 第2步:我本来不知道这两个数是多少。但既然你这么说,那我现在知道了。
    // 这说明:
    // 1、对于乘积为p的所有整数对,至少有一对他们的和是第1步结果之一
    // 2、“我现在知道”说明对于乘积为p的整数对中,只有一对的和是第1步结果之一,如果不止一对的话,“我”还是不能确定。
    // 所以:对于第1步结果中所有可能的整数对,相乘得到p,再统计所有乘积为p的整数对的和在第1步结果中出现的次数,,出现次数为1的即为结果。
    // 结果:整数对为4,13,他们和是s=17,他们的乘积为p=52
    for (int s=MIN*2; s<=MAX*2; s++) {
    if (available[s]) {
    Vector<IntPair> v = getAddFactors(s);
    int index = indexOfAvailableSum(v);
    if (0 <= index) {
    IntPair ip = v.get(index);
    System.out.println("Result is: " + ip.l + "," + ip.r + "  and sum=" + s + ", product=" + ip.l*ip.r);
    }
    }
    }
    // “那我也知道了”是废话。
    } static Vector<IntPair> getAddFactors(int sum) {
    Vector<IntPair> v = new Vector<IntPair>();
    int max = Math.min((int)((sum+1)/2), MAX);
    for (int i=MIN; i<=max; i++) {
    int j = sum - i;
    if ((i <= j) && (j<=MAX)) {
    v.add(new IntPair(i, j));
    }
    }
    return v;
    } static boolean isPrimePair(IntPair ip) {
            for (int i=2; (i*i)<=ip.l; i++) {
                if (ip.l % i == 0) {
                    if ( (ip.r*i)<=MAX ) {
                     return false;
                    }
                }
            }
            for (int i=2; (i*i)<=ip.r; i++) {
                if (ip.r % i == 0) {
                    if ( (ip.l*i)<=MAX ) {
                     return false;
                    }
                }
            }
            return true;
        }    static int indexOfAvailableSum(Vector<IntPair> v) {
         int result = -1;
    int len = v.size();
         int[] count = new int[len];
    for (int i=0; i<len; i++) {
    count[i] = 0;
    IntPair ip = v.get(i);
    int p = ip.l * ip.r;
            for (int j=2; (j*j)<=p; j++) {
                if ((p%j == 0) && (p/j <= MAX)) {
                    if (available[j + p/j]) {
                     count[i]++;
                    }
                }
            }
    } int count1 = 0;
    for (int i=0; i<len; i++) {
    if (1 == count[i]) {
    count1++;
    }
    } if (1 == count1) {
    for (int i=0; i<len; i++) {
    if (1 == count[i]) {
    result = i;
    }
    }
    } return result;
        }
    }class IntPair {
    int l;
    int r;
    IntPair(int i1, int i2) {
    l = i1;
    r = i2;
    }
    }
      

  9.   

    最后的结论:同下:cool1028(…帅·蛋蛋) ( ) 信誉:100    Blog  2006-11-14 18:47:39  得分: 0  
     
     
       
    我只得出一个结论:
    孙膑和庞涓两位牛人的大脑转的比我们的P4双核的还要快多了!