阿里2014年9月笔试中的一个算法设计题--擦黑板剩余数字

5、在黑板上写下50个数字:1至50.在接下来的49轮操作中,每次做如下动作:选取两个黑板上的数字a和b,擦去,在黑板上写|b - a|。请问最后一次动作之后剩下数字可能是什么?为什么?

题目参见:擦黑板剩余数字

当时写这道题目的时候并没有明显的思路,后来感觉应该用归纳法进行分析,但还没有理出来一个思路,程序写出来测试了下,3000次测试结果,剩下的都是奇数。

即,可能生下从1-50范围内的任意奇数

代码如下:

 1             HashSet<int> hsr = new HashSet<int>();
 2             int[] result;
 3             int flag = 3000;
 4             int count = flag;
 5             string inStr;
 6             int inNum;
 7             Console.WriteLine("请输入试验次数:");
 8             inStr=Console.ReadLine();
 9             if (int.TryParse(inStr,out inNum))
10             {
11                 flag= flag > inNum ? flag : inNum;
12                 count = flag;
13                 while (flag > 0)
14                 {
15                     ArrayList hs = new ArrayList();
16                     for (int i = 1; i <= 50; i++)
17                     {
18                         hs.Add(i);
19                     }
20                     int hsCount;
21                     Random rand = new Random();
22                     for (int j = 0; j < 49; j++)
23                     {
24                         int r1, r2, delta;
25                         int e1, e2;
26 
27                         hsCount = hs.Count;
28                         r1 = rand.Next(0, hsCount);
29                         e1 = (int)hs[r1];
30                         hs.RemoveAt(r1);
31                         hsCount = hs.Count;
32                         r2 = rand.Next(0, hsCount);
33                         e2 = (int)hs[r2];
34                         hs.RemoveAt(r2);
35                         delta = Math.Abs(e2 - e1);
36                         hs.Add(delta);
37                     }
38                     if (hs.Count > 0)
39                     {
40                         Console.Write("第{0:d3}次试验:", flag);
41                         foreach (int e in hs)
42                         {
43                             Console.Write("{0:d2}", e);
44                             if (!hsr.Contains(e))
45                             {
46                                 hsr.Add(e);
47                             }
48                         }
49                     }
50                     flag -= 1;
51                     Thread.Sleep(10);
52                     Console.WriteLine();
53                 }
54                 result = (int[])hsr.ToArray();
55                 Array.Sort(result);
56                 Console.WriteLine("{0:d4}次试验结果:", count);
57                 for (int k = 0; k < result.Length; k++)
58                 {
59                     if (!k.Equals(result.Length - 1))
60                     {
61                         Console.Write("{0:d2},", result[k]);
62                     }
63                     else
64                     {
65                         Console.Write("{0:d2}", result[k]);
66                     }
67                 }
68             }
69             else
70             {
71                 Console.WriteLine("请输入正确的整数!");
72                 Environment.Exit(0);
73             }    

该为结果找个有说服力的理论~~~

update(@2013-11-1)偶尔看到恩格尔的《解决问题的策略》(参考链接),刚翻几页就看到这个题目了,解释很简单,使用的是“不变量原理“。更一般的表述如下:

正整数n是奇数,在黑板上写下来1-2n,然后任意取两个数a,b,擦去这两个数并写上|a-b|,证明:最后留下的是一个奇数。

解:设S为黑板上所有数字的和,开始时S=n(2n+1),是个奇数,每一步使S减少2min(a,b),它是个偶数,所以S的奇偶性是个不变量,在整个简化过程中总有S≡1(mod 2),所以最后结果是个奇数。

作者:RonaldHan
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/ronaldhan/p/3343975.html