一道小学五年级的数学题引发的一些思考
2006-08-12 22:53
369 查看
表弟暑假在我家做作业,问我一道题::
学
学习
学习进
+学习进步
————————
2001
四个字各代表一个0-9的数字,问“学习进步”代表多少。
我很惊讶在小学作业中就出现这种题,这道题即使在现在的大学算法课上也会作为一道智力题来考大家,很多人都答不上来~因为这道题需要很强的逻辑思维能力。
这道题的答案是1802。可能细想一下就能做出来,不过作为搞计算机的人,用计算机的方法做出来也不失为一种挑战。
首先想到的就是穷举法。我们都知道加法的交换律,通过交换,原来的加法就成为:
步
进进
习习习
+学学学学
————————
2001
那么设学=a,习=b,进=c,步=d。
#include<stdio.h>
intmain()
{
inta,b,c,d,s;
for(a=0;a<10;a++)
for(b=0;b<10;b++)
for(c=0;c<10;c++)
for(d=0;d<10;d++)
{
s=1111*a+111*b+11*c+d;
/*s=a+(a*10+b)+(a*100+b*10+c)+(a*1000+b*100+c*10+d);不用交换律也可以,其实是等价的*/
if(s==2001){
printf("%3d%3d%3d%3d/n",a,b,c,d);
return0;
}
}
return0;
}
通过计算机挨个排查,最终得出结果。这种方法要进行1803次循环(从0000循环到1802),如果把for(b=0;b<10;b++)换为for(b=9;b>=0;b--)则需要1103次循环。
用这种方法做出来后总觉得不过瘾,实在是太笨的方法了。是否还有更有意思更有效的方法呢?
我们继续使用交换律
当学+1,结果即加上1111,
当习+1,结果即加上111,
当进+1,结果即加上11,
当步+1,结果即加上1,
当学比标准值小1即结果小1111,
即使把习加上9也只有999!
无济于事!
故只由当(学+1)*1111刚好大于2001而学*1111小于2001时学的值最恰当!
学即2001除以1111的取整!
同理习即(2001-1111)除以111的取整。
依此类推!其他可以很轻松的口算出来。
#include<stdio.h>
intmain()
{
intt=0;
inti,v,k;
k=1111;
for(i=1;i<=4;i++){
v=(2001-t)/k;
printf("%3d",v);
t=t+v*k;
k=k/10;
}
system("pause");
return0;
}
在计算机上实现算法仅需4次循环,而穷举则至少要进行1103次循环。
当然问题的解决办法肯定不止这些,如果有新的方法,还请大家提出来。再次还要感谢论坛上的wenzituo()()和其他许多坛友的支持。
学
学习
学习进
+学习进步
————————
2001
四个字各代表一个0-9的数字,问“学习进步”代表多少。
我很惊讶在小学作业中就出现这种题,这道题即使在现在的大学算法课上也会作为一道智力题来考大家,很多人都答不上来~因为这道题需要很强的逻辑思维能力。
这道题的答案是1802。可能细想一下就能做出来,不过作为搞计算机的人,用计算机的方法做出来也不失为一种挑战。
首先想到的就是穷举法。我们都知道加法的交换律,通过交换,原来的加法就成为:
步
进进
习习习
+学学学学
————————
2001
那么设学=a,习=b,进=c,步=d。
#include<stdio.h>
intmain()
{
inta,b,c,d,s;
for(a=0;a<10;a++)
for(b=0;b<10;b++)
for(c=0;c<10;c++)
for(d=0;d<10;d++)
{
s=1111*a+111*b+11*c+d;
/*s=a+(a*10+b)+(a*100+b*10+c)+(a*1000+b*100+c*10+d);不用交换律也可以,其实是等价的*/
if(s==2001){
printf("%3d%3d%3d%3d/n",a,b,c,d);
return0;
}
}
return0;
}
通过计算机挨个排查,最终得出结果。这种方法要进行1803次循环(从0000循环到1802),如果把for(b=0;b<10;b++)换为for(b=9;b>=0;b--)则需要1103次循环。
用这种方法做出来后总觉得不过瘾,实在是太笨的方法了。是否还有更有意思更有效的方法呢?
我们继续使用交换律
当学+1,结果即加上1111,
当习+1,结果即加上111,
当进+1,结果即加上11,
当步+1,结果即加上1,
当学比标准值小1即结果小1111,
即使把习加上9也只有999!
无济于事!
故只由当(学+1)*1111刚好大于2001而学*1111小于2001时学的值最恰当!
学即2001除以1111的取整!
同理习即(2001-1111)除以111的取整。
依此类推!其他可以很轻松的口算出来。
#include<stdio.h>
intmain()
{
intt=0;
inti,v,k;
k=1111;
for(i=1;i<=4;i++){
v=(2001-t)/k;
printf("%3d",v);
t=t+v*k;
k=k/10;
}
system("pause");
return0;
}
在计算机上实现算法仅需4次循环,而穷举则至少要进行1103次循环。
当然问题的解决办法肯定不止这些,如果有新的方法,还请大家提出来。再次还要感谢论坛上的wenzituo()()和其他许多坛友的支持。
相关文章推荐
- 一道小学五年级的数学暑假作业引人思考
- 一道小学题引发的思考
- 一道小学五年级的数学题
- 一道小学数学题引发的“血案”
- 一道数学题引发的思考
- Objective-C关于id引发的一些思考
- 一道原生js题目引发的思考(鼠标停留区块计时)
- 一道有意思的笔试题引发的对于new操作符的思考
- 一道JS面试题目引发的思考
- 从文档的编写问题引发的一些思考
- 使用单元测试引发的一些思考
- 由一道腾讯面试题引发对于关联数组的思考
- 某小学一年级暑假作业的一道数学题解答
- 由内部类引发的Android内存泄漏的一些思考
- 小学数学题一道
- 一道迅雷笔试题引发的思考?—— 不重复随机算法
- JAVA学习提高之---- 一道面试题引发的思考之:类的初始化
- 一道面试题引发的有关随机数的思考(5)
- 一道面试题引发的有关随机数的思考(8)
- 如何在PHP中保持SESSION以及由此引发的一些思考