一道小学五年级的数学题引发的一些思考

来源:互联网 发布:qq浏览器3.1java通用版 编辑:程序博客网 时间:2024/04/27 18:13
  
 
表弟暑假在我家做作业,问我一道题::
             
            学习
          学习进
 +    学习进步
————————
        2 0 0 1
四个字各代表一个0-9的数字,问“学习进步”代表多少。
 
我很惊讶在小学作业中就出现这种题,这道题即使在现在的大学算法课上也会作为一道智力题来考大家,很多人都答不上来~因为这道题需要很强的逻辑思维能力。
 
       这道题的答案是1802。可能细想一下就能做出来,不过作为搞计算机的人,用计算机的方法做出来也不失为一种挑战。
 
首先想到的就是穷举法。我们都知道加法的交换律,通过交换,原来的加法就成为:
             
            进进
          习习习
 +    学学学学
————————
        2 0 0 1
那么设学=a,习=b,进=c,步=d。
#include<stdio.h>
int main()
{
    int a,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);
                                                  return 0;
                                                 }
                   }
    return 0;
}
通过计算机挨个排查,最终得出结果。这种方法要进行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>
int main()
{
int t=0;
int i,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");
return 0;
}
在计算机上实现算法仅需4次循环,而穷举则至少要进行1103次循环。
当然问题的解决办法肯定不止这些,如果有新的方法,还请大家提出来。再次还要感谢论坛上的wenzituo() ( ) 和其他许多坛友的支持。