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),所以最后结果是个奇数。