|
4 | 4 |
|
5 | 5 | - [“红色眼睛与褐色眼睛”谜题](#红色眼睛与褐色眼睛谜题)
|
6 | 6 | - [找出剩下的一个数](#找出剩下的一个数)
|
| 7 | +- [2199年7月2日是星期几?](#2199年7月2日是星期几?) |
7 | 8 |
|
8 | 9 | ## “红色眼睛与褐色眼睛”谜题
|
9 | 10 | 从前,有个小岛上只住着和尚。有些和尚的眼睛是红色的,而另一些则是褐色的。红色眼睛的和尚受到诅咒,如果得知自己的眼睛是红色的,那么当晚 12 点必须自行了断,无一例外。
|
@@ -55,4 +56,61 @@ for (int i = 0; i < 100; ++i) {
|
55 | 56 | System.out.println("最后剩下的数是:" + res);
|
56 | 57 | ```
|
57 | 58 |
|
58 |
| -如果将集合的 100 个数值累加,会得到 5050。依次从 5050 减去数组中的 99 个数值,最后的数就是没能保存到数组的那个剩余数值。也许很多读者想到了与此相近的算法。即使没有得到正确答案也不用失望,因为真正应该感到失望的人是那些没能找到答案后轻易选择放弃、想要直接查看正确答案的人。 |
| 59 | +如果将集合的 100 个数值累加,会得到 5050。依次从 5050 减去数组中的 99 个数值,最后的数就是没能保存到数组的那个剩余数值。也许很多读者想到了与此相近的算法。即使没有得到正确答案也不用失望,因为真正应该感到失望的人是那些没能找到答案后轻易选择放弃、想要直接查看正确答案的人。 |
| 60 | + |
| 61 | +## 2199年7月2日是星期几? |
| 62 | +先公布答案吧,2199年7月2日是星期二。其实可以靠运气蒙一下,准确率是 1/7。要想真正求出正确答案,过程并不简单。也许有些读者会自己设计精妙算法求出正确答案,但我还是想通过约翰•康威教授的“末日”算法进行说明。 |
| 63 | + |
| 64 | +末日算法虽然不是“游戏”,但在聚会中能够引起初次见面的异性的好奇。因此,为不少“花花公子”踏入数学殿堂做出了很大贡献。例如,“美丽的女士,求告诉我您的生日,让我猜猜是星期几。”“请您随便说一个年份,我会猜出当年的情人节是星期几”。虽然听起来比较肉麻,不过这样就能一下子吸引对方的注意。 |
| 65 | + |
| 66 | +康威教授的末日算法执行环境就是我们今天使用的“公历”环境。 |
| 67 | + |
| 68 | +首先,先理清楚**什么是闰年**。闰年是年份能被 4 整除但不能被 100 整除,或者能被 400 整除的年份。闰年 2 月有 29 天,而平年 2 月是 28 天。 |
| 69 | + |
| 70 | +```java |
| 71 | +// 判断是否是闰年 |
| 72 | +boolean isLeapYear(int year) { |
| 73 | + return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +康威末日算法的运行原理非常简单。为了判断不同日期的星期,算法中首先**设立一个必要的“基准”**。然后,**根据星期以 7 为循环的原则和对闰年的考虑**,计算日期对应的星期。 |
| 78 | + |
| 79 | +平年时,将 2.28 日设置为“末日”;到了闰年,将 2.29 日设置为“末日”。只要知道了特殊年份(e.g. 1900 年) “末日”的星期,那么根据康威算法即可判断其它日期的星期。 |
| 80 | + |
| 81 | +我们都知道,星期以 7 为循环,所以与“末日”以 7 的倍数为间隔的日期就和“末日”具有相同的星期。利用这个原理,先记住每个月中总是与“末日”星期相同的一个日期,即可快速算出结果。 |
| 82 | + |
| 83 | +每个月与“末日”具有相同星期的一天分别是: |
| 84 | + |
| 85 | +``` |
| 86 | +4.4、6.6、8.8、10.10、12.12、9.5、5.9、7.11、11.7、3.7 |
| 87 | +``` |
| 88 | + |
| 89 | +只需要记住 4、6、6、10、12 这几个月与日的数字相同,然后是 9.5、5.9、7.11、11.7,这几个是对称的,还有一个是 3.7。是不是很容易记住? |
| 90 | + |
| 91 | +好了,那么我们**只要知道当年的“末日”是星期几,就可以推算出当年的任何一天是星期几了**。 |
| 92 | + |
| 93 | +举个例子吧。2003 年的“末日”是星期五,我们推算一下那一年的圣诞节的星期。由于 2003 年“末日”是星期五,所以 12 月 12 日也是星期五(我们上面记住了每个月与“末日”具有相同星期的一天),那么 `12+7*2=26`,12 月 26 日也是星期五,所以 12 月 25 日是星期四。 |
| 94 | + |
| 95 | +那么问题来了,**怎么才能知道某一年的“末日”是星期几呢**? |
| 96 | + |
| 97 | +这种情况下,需要记住“末日”的星期每跨 1 年就会加 1,若遇到闰年就会加 2。 |
| 98 | + |
| 99 | +例如,1900 年的“末日”是星期三,那么 1901 年的“末日”是星期四(+1),1902 年的“末日”是星期五(+1),1903 年的“末日”是星期六(+1),而 1904 年(闰年)的“末日”是“星期一”(+2)。 |
| 100 | + |
| 101 | +就是说,我们记住了 1900 年“末日”是星期三,就可以推算出其它年份的“末日”是星期几了。 |
| 102 | + |
| 103 | +这样一个个推算还是很麻烦,可能一不小心就推错了。为此,康威教授贴心地给我们提供了如下形式的列表。 |
| 104 | + |
| 105 | +``` |
| 106 | +6, 11.5, 17, 23, 28, 34, 39.5, 45, 51, 56, 62, 67.5, 73, 79, 84, 90, 95.5 |
| 107 | +``` |
| 108 | + |
| 109 | +就是说,1900 年“末日”是星期三,那么 1906,1917,1923... “末日”也是星期三, 11.5 表示 1911 年的“末日”是星期二(-1),而1912 年的“末日”是星期四(+1)。记住这个列表,我么就能够胜场所有 20 世纪年份的“末日基准”了。 |
| 110 | + |
| 111 | +如果一个美丽的姑娘说“我的生日是 1992.9.13” 时,我们可以马上说出当天的星期。既然康威列表有 90 这个数字,表示 1990 年的“末日”也是星期三,那么 1901 年(平年)“末日”是星期四(+1),1902 年(闰年)“末日”是星期六(+2),所以 9.5/9.12 也是星期六,1992.9.13 就是星期日。 |
| 112 | + |
| 113 | +不过,**年份跨越世纪时,康威列表就会失去作用**。 |
| 114 | + |
| 115 | + |
| 116 | + |
0 commit comments