以下面的结论为基础,可以创作很多扑克牌小魔术。设正整数 n、k 满足 n ≤ 2k ≤ 2n。将 n 张牌叠成一摞,然后用发牌的方式把上面 k 张牌发成一摞,再把剩余的牌叠上去。整个过程再重复三次,则这 n 张牌会变回成原顺序。
证明:
以下面的结论为基础,可以创作很多扑克牌小魔术。设正整数 n、k 满足 n ≤ 2k ≤ 2n。将 n 张牌叠成一摞,然后用发牌的方式把上面 k 张牌发成一摞,再把剩余的牌叠上去。整个过程再重复三次,则这 n 张牌会变回成原顺序。
证明:
正四面体、正方体、正八面体、正十二面体、正二十面体,这是古希腊人就发现的五种正多面体,它们拥有最高标准的对称性。这五种正多面体又叫做 Platonic 体,它们在古希腊的哲学观念中占据着至关重要的地位。 Leonhard Euler 发现,多面体的顶点数 V 、棱数 E 和面数 F 一定满足公式 V – E + F = 2 ,这叫做 Euler 多面体公式。利用这个公式,我们可以证明正多面体只有五种。假设一个正多面体的每个面都是正 p 边形,那么所有 F 个面一共就有 p · F 条边;每两条边拼在一起形成了一条棱,因而总的棱数就是 E = p · F / 2 。反过来, F 就应该等于 2 · E / p 。不妨再假设每个顶点处都汇集了 q 条棱,那么总的棱数似乎应有 q · V 个;但这样计算的话,每条棱都被重复算了两次,因而总的棱数实际上应该是 E = q · V / 2 。反过来, V 就应该等于 2 · E / q 。另外, Euler 的多面体公式告诉我们, V – E + F = 2 始终成立。
把上面几个式子合在一起,于是得到:
2 · E / q – E + 2 · E / p = 2
整理可得:
1/p + 1/q – 1/2 = 1/E
因此, 1/p + 1/q 一定大于 1/2 。但是,正多面体每个面至少都有三条边,每个顶点也至少汇集了三条棱,因此 p 和 q 都是大于等于 3 的整数。要想 1/p + 1/q > 1/2 ,只有以下五种可能:
这正好对应于那五种正多面体。最近 Localhost-8080 沉迷于折纸,我也因此学习了不少与多面体相关的东西。想不到,这些看似老生常谈的东西,里面的水可深着呢。这五种正多面体表面上只是问题的五个不同的解,但互相之间却有着出人意料的联系。我们再列一个更加完整的表格,有意思的东西会慢慢呈现出来:
名称 | 面数 F | 顶点数 V | 棱数 E | 每个面的边数 p | 每个顶点处的棱数 q |
正四面体 | 4 | 4 | 6 | 3 | 3 |
正方体 | 6 | 8 | 12 | 4 | 3 |
正八面体 | 8 | 6 | 12 | 3 | 4 |
正十二面体 | 12 | 20 | 30 | 5 | 3 |
正二十面体 | 20 | 12 | 30 | 3 | 5 |
Kyle McCormick 在 StackExchange 上发起了一个叫做 Tweetable Mathematical Art 的比赛,参赛者需要用三条推这么长的代码来生成一张图片。具体地说,参赛者需要用 C++ 语言编写 RD 、 GR 、 BL 三个函数,每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数(0 ≤ i, j ≤ 1023),然后需要返回一个 0 到 255 之间的整数,表示位于 (i, j) 的像素点的颜色值。举个例子,如果 RD(0, 0) 和 GR(0, 0) 返回的都是 0 ,但 BL(0, 0) 返回的是 255 ,那么图像的最左上角那个像素就是蓝色。参赛者编写的代码会被插进下面这段程序当中(我做了一些细微的改动),最终会生成一个大小为 1024×1024 的图片。
// NOTE: compile with g++ filename.cpp -std=c++11
#include <iostream>
#include <cmath>
#include <cstdlib>
#define DIM 1024
#define DM1 (DIM-1)
#define _sq(x) ((x)*(x)) // square
#define _cb(x) abs((x)*(x)*(x)) // absolute value of cube
#define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root
unsigned char GR(int,int);
unsigned char BL(int,int);
unsigned char RD(int i,int j){
// YOUR CODE HERE
}
unsigned char GR(int i,int j){
// YOUR CODE HERE
}
unsigned char BL(int i,int j){
// YOUR CODE HERE
}
void pixel_write(int,int);
FILE *fp;
int main(){
fp = fopen("MathPic.ppm","wb");
fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM);
for(int j=0;j<DIM;j++)
for(int i=0;i<DIM;i++)
pixel_write(i,j);
fclose(fp);
return 0;
}
void pixel_write(int i, int j){
static unsigned char color[3];
color[0] = RD(i,j)&255;
color[1] = GR(i,j)&255;
color[2] = BL(i,j)&255;
fwrite(color, 1, 3, fp);
}
下面大家将会看到的是一个极其简单而又极其复杂的“迷宫”,这无疑是我在本年度见到的最变态的谜题:从左边入口处的 2011 进去,在迷宫里转悠,最后变成 2012 从右边出来。你可以在迷宫里转圈,可以重复之前走过的路,但不能往回退着走。
你能成功走出来吗?