**********
趣味思考题:请通过编程求解如下孙膑和庞涓问题。
庞涓拿到两个整数(这个整数均在2到99之间)之和,孙膑拿到这两个整数之积。下面是一段很有趣的对话。
庞涓说:我不知道这两个整数是多少,但我肯定你也不知道。
孙膑说:我本来不知道这两个数是多少。但既然你这么说,那我现在知道了。
庞涓说:哦,那我也知道了。
要求输出所有可能的结果,包括这两个整数、这两个整数之和以及这两个整数之积。
**********
会的大哥大姐们帮忙解决一下,thanks....
趣味思考题:请通过编程求解如下孙膑和庞涓问题。
庞涓拿到两个整数(这个整数均在2到99之间)之和,孙膑拿到这两个整数之积。下面是一段很有趣的对话。
庞涓说:我不知道这两个整数是多少,但我肯定你也不知道。
孙膑说:我本来不知道这两个数是多少。但既然你这么说,那我现在知道了。
庞涓说:哦,那我也知道了。
要求输出所有可能的结果,包括这两个整数、这两个整数之和以及这两个整数之积。
**********
会的大哥大姐们帮忙解决一下,thanks....
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)");
}
}}
^_^ 最笨的方法
//打印出可能的组合数
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; }
方便描述,假设:有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
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));
}
}
}
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));
}
}
} }
那么A说你一定猜不出就不准确了,所以s<55
”实在是难以理解,没办法,大学数学,全部还给老师了。请教一下猪猪,如果积为1890,和为97(两数为27,70);或者积为1890,和为93(30,63)的话,又有哪里不符合题目要求呢?
下面是我作为一个程序员的思路,我觉得简单很多。假设:和为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
“那我也知道了”是废话。还有不明白的提出来,继续讨论。
程序见下
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;
}
}
我只得出一个结论:
孙膑和庞涓两位牛人的大脑转的比我们的P4双核的还要快多了!