小偷也要会数学:暴力破解的偷懒方法 | 科学人 | 果壳网 科技有意思



小偷也要会数学:暴力破解的偷懒方法 | 科学人 | 果壳网 科技有意思

很多保险箱的密码都是四位数,这足以给人带来安全感——由于从 0000 到 9999 共有 10000 种情况,要想试遍所有的密码,按 40000 次数字键似乎是必需的。但是,很多保险箱的数字键盘上并没有输入键。只要连续输入的四个数字恰好和预先设定的密码相同,保险箱都会打开。比如说,当你尝试输入 1234 和 1235 两个密码时,2341、3412、4123 也被试过了。聪明的小偷可以利用这一特性,设计出一种数字输入顺序,大大减少最坏情况下需要的总按键次数。你认为,试遍所有的密码最少需要按多少个键呢?

如果一个数字序列包含了 10000 个不同的四位数,这个数字序列至少得有 10003 位长。令人吃惊的是,真的就存在这么一个 10003 位的数字序列,它既无重复又无遗漏地包含了所有可能的四位数。更神的是,满足要求的数字序列不止一种,而寻找数字序列的任务竟完全等价于一笔画问题!

为了把事情解释清楚,不妨让我们先来看一个更为简单的问题:假如密码是一个只由数字 0 和 1 构成的三位数(这有 8 种可能的情况),如何构造一个 10 位数字串,使它正好包含所有可能的三位数?现在,让我们在图上画四个点,分别标记为 00、01、10、11,它们表示数字串中相邻两个数字可能形成的 4 种情况。如果某个点上的数的后面一位,恰好等于另一个点上的数的第一位,就从前面那个点出发,画一个到后面那个点的箭头,表示从前面那个点可以走到后面这个点。举例来说,00 的后一位数正好是 01 的前一位数,则我们画一个从 00 到 01 的箭头,意即从 00 可以走到 01。注意,有些点之间是可以相互到达的(比如 10 和 01),有些点甚至有一条到达自己的路(比如 00)。

http://www.guokr.com/gkimage/h9/mh/9n/h9mh9n.png

图上有 00、01、10、11 四个点,如果两个点满足 xy 和 yz 的关系(x、y、z 有可能代表相同的数字),就画一条从 xy 到 yz 的路,这条路就记作 xyz

试密码的过程,其实就相当于沿着箭头在上图中游走的过程。不妨假设你最开始输入了 00。如果下一次你输入了 1,那么你就试过了 001 这个密码,同时你最近输过的两位数就变成了 01;如果你下一次还是输入的 0,那么你就试过了 000 这个密码,你最近输过的两个数仍然是 00。从图上看,这无非是一个从 00 点出发走了哪条路的问题:你是选择了沿 001 这条路走到了 01 这个点,还是沿着 000 这条路走回了 00 这个点。同理,你每按下一个数字,就相当于沿着某条路走到了一个新的点,路上所写的三位数就是你刚才试过的密码。我们的问题就可以简单地概括为,如何既无重复又无遗漏地走完上图中的所有路。也就是说,我们要解决的仅仅是一个一笔画问题!

稍试几下,我们便可以找出一条一笔画路径。其中一条路就是:

00 → 00 → 01 → 10 → 01 → 11 → 11 → 10 → 00

它给出了一个满足要求的 10 位数字序列:

0001011100

这个 10 位数字串就真的包含了全部 8 个由 0 和 1 构成的三位数!事实上,利用一些图论知识,我们可以直接看出这个图一定能一笔画走完的。在图论中,从一个顶点延伸出去的箭头数叫做这个点的"出度",而指向这个顶点的箭头数则叫做这个顶点的"入度"。图论中有一个重要的定理:对于一个连通的图,如果每个点的出度都等于入度,那么一定能够找到一种经过每条路恰好一次的走法。很显然,在上图中,从任意一点出发,都有两条路可以走;同时,走到这个点也总有两种不同的途径。这就告诉我们,遍历所有路恰好一次的方法是一定存在的。

同样地,对于 0 到 9 组成的全部四位数来说,我们可以设置 1000 个顶点,分别记作 000, 001, …, 999。如果某个数的后两位等于另一个数的前两位,就从前者出发,画一个箭头指向后者。容易想到,每个顶点的入度和出度都是 10,因此存在一条一笔画路径。也就是说,只需要按 10003 次数字键,便能试遍所有可能的四位数密码了。

虽然我们利用数学证明了符合要求的数字序列一定存在,但这个 10003 位数究竟是多少呢?这时,就轮到计算机登场了。利用计算机程序,我们可以很快给出一个答案;限于篇幅,我们就不在这里展示了,欢迎大家到 死理性派小组 里围观。


Read full article from 小偷也要会数学:暴力破解的偷懒方法 | 科学人 | 果壳网 科技有意思


No comments:

Post a Comment

Labels

Algorithm (219) Lucene (130) LeetCode (97) Database (36) Data Structure (33) text mining (28) Solr (27) java (27) Mathematical Algorithm (26) Difficult Algorithm (25) Logic Thinking (23) Puzzles (23) Bit Algorithms (22) Math (21) List (20) Dynamic Programming (19) Linux (19) Tree (18) Machine Learning (15) EPI (11) Queue (11) Smart Algorithm (11) Operating System (9) Java Basic (8) Recursive Algorithm (8) Stack (8) Eclipse (7) Scala (7) Tika (7) J2EE (6) Monitoring (6) Trie (6) Concurrency (5) Geometry Algorithm (5) Greedy Algorithm (5) Mahout (5) MySQL (5) xpost (5) C (4) Interview (4) Vi (4) regular expression (4) to-do (4) C++ (3) Chrome (3) Divide and Conquer (3) Graph Algorithm (3) Permutation (3) Powershell (3) Random (3) Segment Tree (3) UIMA (3) Union-Find (3) Video (3) Virtualization (3) Windows (3) XML (3) Advanced Data Structure (2) Android (2) Bash (2) Classic Algorithm (2) Debugging (2) Design Pattern (2) Google (2) Hadoop (2) Java Collections (2) Markov Chains (2) Probabilities (2) Shell (2) Site (2) Web Development (2) Workplace (2) angularjs (2) .Net (1) Amazon Interview (1) Android Studio (1) Array (1) Boilerpipe (1) Book Notes (1) ChromeOS (1) Chromebook (1) Codility (1) Desgin (1) Design (1) Divide and Conqure (1) GAE (1) Google Interview (1) Great Stuff (1) Hash (1) High Tech Companies (1) Improving (1) LifeTips (1) Maven (1) Network (1) Performance (1) Programming (1) Resources (1) Sampling (1) Sed (1) Smart Thinking (1) Sort (1) Spark (1) Stanford NLP (1) System Design (1) Trove (1) VIP (1) tools (1)

Popular Posts