趣味数学编程题解之身份证号码之谜

IT商界

  循环的形式有好多种,具体选择哪种须根据实际情况来决定。即使是同一题目,用同样的循环语句形式,也可有很多解法。

  要找出题中的关系,就看你分析问题的角度了。不同的角度,分析方法就不同,得到的结果却是一样的。这是编程的另一种魅力。

  本期介绍的故事也是发生在警察局,这个故事和前面介绍过的车牌号码的故事有点异曲同工的味道。在车牌问题上,我们是从整体着手研究各个数字。这次,我们反其道而行之,看看究竟行不行。

  题目:身份证号码之谜

  这是发生在外国警察局中的一个故事,已知某人身份证号码扣除第一个英文字母后是9位数,现在有一个人的身份证号码中前1位可以被1的平方整除、前2位可以被2的平方整除、前3位可以被3的平方整除,前4位可以被4的平方整除,而从第5位开始,前5位可以被5整除……以此类推至前9位可以被9整除。你可以帮他们找出这一个人的身份证号码吗?例:123456789中前1位是1、前2位是12,可被2的平方4整除等。

  分析本案的已有线索和将来要的结果

  对于上面的案子,要做的其实很简单,根据9个被整除的信息,得出一个身份证号码来。仔细分析一下,9个条件其实最终只有8个条件,因为任何一个整数都可被1来整除。

  我们可以参照《身份证号码之谜》中的做法,直接设上一个九位数n,然后找出其中的9个数位,最后将条件做出来。另外还有一种更为简洁的办法:

  可以将9个数位用变量a1,a2,……a9来代表,每个数位的取值范围自然是0~9,总计10个数字。有了各位上的数字,怎样来组合题中对我们有用的9个条件呢?

  (1)前1位可以被1的平方整除。

  这个条件没什么意义,所有的数都符合。

  (2)前2位可以被2的平方整除。

  这个条件就开始有点意思了。首先要将前两位数组合出来:

  a1*10+a2这就是前两位组成的数,这个数能被2的平方也就是4整除,用公式表示是(a1*10+a2)mod 4=0(mod是取余数的运算)。

  (3)前3位可以被3的平方整除。

  受第2个条件启发,这个条件也就成了:前三位数为(a1*100+a2*10+a3),整除的条件自然就成了:

  (a1*100+a2*10+a3)mod 9=0

  (4)第4个条件和(3)类似。

  (5)第5~9个条件只要将(3)稍做变化,也就出来了。

  前五位数为(a1*10000+a2*1000+a3*100+a4*10+a5),整除的条件自然就成了:

  (a1*10000+a2*1000+a3*100+a4*10+a5)mod 5=0。由于表达式太长,可设一个数n来代表前面表达的数值。

  (6~9)第6~9个条件只要将(5)稍做变化,就出来了。

  处理过程的分析

  通过上面对条件和结果的分析,处理过程也就明确了,我们让电脑做的工作是什么呢?实质上就是将a1在0~9,a2在0~9之间…… a3在0~9之间组成的000000000~999999999之间符合前面我们所列的9个条件的数列,最后得到的数也就是我们的所求了。所以程序的大体结构是9个循环并且内部有分支语句。

  本题最大的特点还是循环,有9个循环套在一起。为什么能用这么多循环呢,和上面的10亿个数字的特点不无关系。如果从每个数位上去看,特点便是循环中出现循环的特点。

  至于循环中的条件呢?因为不是各个条件对9个循环都是需要的,第1个循环只和第一个条件相联系,第2个循环和第2个条件相联系,这就决定了9个条件不是连在一起的,而是分散发挥作用的,这是我们需注意的是第二点。

  为了更加便于初学者学习和模仿,N—S图我们只给到第三重循环(如图),其他的几重循环的特点跟前面(2)和(3)重循环相似,在第九重循环内的分支的Y部分,则是输出a1、a2到a9组成的数字的语句。请你根据题目自己向下画画试试吧。

  语言、界面、源程序

  (1)语言

  程序中通过Virual BASIC6.0语言来实现。

  (2)界面

  界面非常简单,建立一标准EXE工程,其Caption设为“身份证号码之谜”,并加入两个命令按钮Cmdsearch和Cmdexit,Caption改为“查找”和“退出”,输出的结果放在一名为“txtlist”的文本框中。我们将代码加给cmdsearch_Click()即查找按钮的单击事件,将来运行时,我们只要用鼠标单击一下按钮,程序就执行了,结果会在文本框中显示。

  (3)源程序

  从N-S图中我们不难看到,程序的整体结构是一个循环(以a1为循环变量),而后的循环(a2~a9)都符合循环嵌套分支的形式。我们写程序时只要把这种嵌套的关系把握好,程序也就不难写出了。源程序如下:

  Option Explicit

  Dim n As Long

  Private Sub CmdExit_Click() '退出按钮

  Unload Me

  End Sub

  Private Sub CmdSearch_Click() '查找按钮

  Dim a1, a2, a3, a4, a5, a6, a7, a8, a9 As Integer

  Dim knum As Integer '符合条件计数器

  TxtList.Text = "" '清空文本框

  n = 0

  knum = 0

  ‘程序主要代码

  For a1 = 0 To 9

  '条件1

  For a2 = 0 To 9

  '条件2

  n = a1 * 10 + a2

  If n Mod 4 = 0 Then

  For a3 = 0 To 9

  '条件3

  n = a1 * 100 + a2 * 10 + a3

  If n Mod 9 = 0 Then

  For a4 = 0 To 9

  '条件4

  n = a1 * 1000 + a2 * 100 + a3 * 10 + a4

  If n Mod 16 = 0 Then

  For a5 = 0 To 9

  '条件5

  n = a1 * 10000 + a2 * 1000 + a3 * 100 + a4 * 10 + a5

  If n Mod 5 = 0 Then

  For a6 = 0 To 9

  '条件6

  n = a1 * 100000 + a2 * 10000 + a3 * 1000 + a4 * 100 + a5 * 10 + a6

  If n Mod 6 = 0 Then

  For a7 = 0 To 9

  '条件7

  n = a1 * 1000000 + a2 * 100000 + a3 * 10000 + a4 * 1000 + a5 * 100 + a6 * 10 + a7

  If n Mod 49 = 0 Then

  For a8 = 0 To 9

  '条件8

  n = a1 * 10000000 + a2 * 1000000 + a3 * 100000 + a4* 10000 + a5 * 1000 + a6 * 100 + a7 * 10 + a8

  If n Mod 8 = 0 Then

  For a9 = 0 To 9

  '条件9

  n = a1 * 100000000 + a2 * 10000000 + a3 * 1000000 + a4 * 100000 + a5 * 10000 + a6 * 1000 + a7 * 100 + a8 * 10 + a9

  If n Mod 9 = 0 Then

  knum = knum + 1 '计数增长

  ‘输出9位数TxtList.Text = TxtList.Text + Str(knum) + ":" + Trim(Str(a1)) + Trim(Str(a2)) + Trim(Str(a3)) + Trim(Str(a4)) + Trim(Str(a5)) + Trim(Str(a6)) + Trim(Str(a7)) + Trim(Str(a8)) + Trim(Str(a9)) + vbCr + vbLf

  End If

  Next a9

  End If

  Next a8

  End If

  Next a7

  End If

  Next a6

  End If

  Next a5

  End If

  Next a4

  End If

  Next a3

  End If

  Next a2

  Next a1

  '上面是程序的主要代码

  End Sub

  (上程序在VB6、Win2000下调试通过)

  编程小结

  有了程序,身份证号码的范围被大大缩小了,不是我们通常想象的只有1个结果,结果有20个。究竟哪一个最符合警察们的需要,我们就不必知晓了。不过,编这个程序告诉我们最重要的一点不是程序的难易,而是耐心。

  分析问题的方法有好多,形式也有好多,关键是根据具体的情况进行选择,选择适当的语句,选择适当的语句组合形式。有了这种整体的把握,分析问题的能力又成为编程的一项考验。下一期我们继续研究一下编程辅助工具N-S图,通过它来帮助我们解决实际问题。