分段数组是近年来选考VB中的热门考点,各种联考卷或模拟卷中也出现了大量相关的题目。常见的一种应用是把一个长度为n的数组a,等分成n\k段(其中每段元素个数为k),若最后有不足k个元素,则自成一段。给每段设置一个编号,问下标为i的元素所在段的编号num是多少?
题目要求的是段编号num和元素下标i的关系。如果我们默认数组元素下标从0开始(很多编程语言都是这样做的),段编号也是从0开始,那么很容易得到:num = i \ k。 但是,我们在平时的VB教学中,为了适应学生的思维习惯,通常设置数组元素下标从1开始,段编号也从1开始。(顺便说一句,这种处理方法虽然符合日常的思维习惯,但是为编程带来了不利,因为从变量寻址的角度来说,设置第一个数组元素的下标为0,更便于编写代码)。 稍作分析,也可以得到表达式: num = (i – 1) \ k + 1。 两式对比一下,其实就是先让元素下标i减1,使得数组元素下标从0开始,这样可以得到从0开始的段编号;再让段编号加1,使得段编号从1开始。 理解了上述两个表达式以后,我们就可以利用它解决一些看似复杂的分段数组问题了。2019学年第一学期浙江“七彩阳光”联盟期初联考第16题
一 题目16.某字符转置算法描述如下:
● 将字符串(均为大写字符) s依次转换为相对应的数值(字符A ~Z对应数值1~26);
● 转换后的数值以K个数据为段,将n个待处理的数据依次分割成若干段(最后一段不足部分用0来补充);
● 每一段中K个数据与K*K转置矩阵进行乘法运算;
● 将乘法运算得到的每一个结果值除以26求余数,依次转换成相应字符(数值1~26对应字符A~Z),最后按原始字符串长度输出。
乘法运算规则如下:
第i个元素c(i)= 第j个元素a(j)*转置矩阵第i行第j个元素b(t)的乘积之和(其中j=1,2..k)
例如:字符串s= “PYTHON”,区块大小K=4的转置过程如下:
(1)根据算法描述,上述示例中,字符“N”的相乘结果(即图中(★)处)为____。
(2)请在划线处填入合适代码。
Private Sub Command1_Click()
Dim a(1 To 100) As Integer '存储字符串,长度不超过100个字符
Dim b(1 To 100) As Integer '存储转置矩阵,长度不超过10*10
Dim c(1 To 100) As Long
Dim s As String, tmp As String:
Dim k As Integer, t As Integer, i As Integer, j As Integer
Dim n As Integer, m As Integer, lens As Integer
s = Text1.Text '在Text1中输入原始字符串
k = Val(Text2.Text) '在Text2中输入区块大小k
Randomize
For i = 1 To k ^ 2
b(i) = Int(Rnd * 9) + 1
tmp = tmp + Str(b(i))
If i Mod k = 0 Then
List2.AddItem tmp
tmp = ""
End If
Next i
lens = Len(s): n = lens
For i = 1 To n
tmp = Mid(s, i, 1)
①
List1.AddItem Str(a(i))
Next i
Do While n Mod k = 0
n = n + 1
a(n) = 0
List1.AddItem Str(a(n))
Loop
For i = 1 To n
m = (i - 1) Mod k + 1
t = 1
For j = ②
c(i) = a(j) * b((m - 1) * k + t) + c(i)
t = t + 1
Next j
Next i
For i = 1 To n
List3.AddItem Str(c(i))
Next i
s = ""
For i = 1 To lens
③
s = s + Chr(t + 64)
Next i
Text3.Text = s
End Sub
二 考查知识点 分段数组、矩阵乘法、字符串转换。要求学生熟练字符串转换基本操作,理解分段数组中段编号num和元素下标i的关系,能根据题意分析各个变量的含义,理解算法思想。 三解析此题背景信息繁复,数据结构复杂,涉及变量较多,很考验学生的阅读理解能力。但算法说明还算清晰,示例数据也很恰当,示意图简明易懂,如果有足够时间,应该不难理解题意。
当然因为使用自然语言对算法进行描述很难做到完全准确,有些不精确的措辞对读者进行了误导,例如题目中对乘法运算规则的描述就不够准确,最后一步所谓“将乘法运算得到的每一个结果值除以26求余数”,也不是精确的描述。
第一小题计算式:15*5+14*1+0*2+0*9 = 89。
第二小题第①空所在的代码段(for循环)的作用是将字符串 s依次转换为相对应的数值,并输出到列表List1。其中第①空的作用将大写字母tmp转换为相对应的数值(字符A ~Z对应数值1~26),故答案为a(i) = Asc(tmp) - Asc(“A”) + 1。
第③空所在的代码段(for循环)的作用是将c(i)依次转换成转置后的字符,并拼接成字符串s。其中第③空的作用是将c(i)转换成与字符相对应的数值t,因为数值1~26对应字符A~Z,故不能把t简单理解成c(i) Mod 26,否则会使得0<=t<=25。要想t的范围是1~26,则必须写成t = (c(i) – 1 ) Mod 26 + 1。
当然,也可以用语句t = c(i) Mod 26 : s = s + Chr(t + 65)代替原来循环体内代码。
本题最难的是第②空。其所在二重循环语句的作用是依次将每一段中K个数据与K*K转置矩阵进行乘法运算。
其中变量i代表第i个字符,我们将字符串分段,每段k个元素,则m代表a(i)在所属段中的位置,我们让a(i)所在段的元素分别与转置矩阵中第m行对应的元素相乘,再求和,即得到与a(i)对应的c(i)。
程序让变量j遍历a(i)所在段的所有元素,让变量t遍历转置矩阵中第m行的每一个元素,即m和t分别代表转置矩阵中各元素的行号和列号。
因为a(i)在其所属段中排行m,故a(i)所属段中第一个元素的下标为i – m + 1,最后一个元素的下标为i – m + k。则第②空答案为i - m + 1 To i - m + k。
除此之外,我们也可以从另外一个角度得到第②空答案:
我们设a(i)所在段的编号为num = (i – 1) \ k + 1,则该段第一个元素的下标为(num-1)*k+1,最后一个元素的下标为num*k。则第②空答案为((i - 1) \ k) * k + 1 To ((i - 1) \ k) * k + k。
四 答案(1) 89 (1分)
(2) ① a(i) = Asc(tmp) - 64 或 a(i) = Asc(tmp) - Asc(“A”) + 1 (2分)
② i – m + 1 To i – m + k
或((i - 1) \ k) * k + 1 To ((i - 1) \ k) * k + k 或其他等价表达式 (2分)
③t = (c(i) – 1 ) Mod 26 + 1 (2分)
五拓展思考16.【浙江省名校新高考研究联盟(Z20联盟)2020届第一次联考】给定一个数组 a,有 n 个元素(1≤n≤100),有以下两种操作:
操作 1:在文本框中分别输入 L、R、T(1≤L≤R≤n),对数组下标为L到R之内(包含L和R))的每个元素增加 T(1≤T≤100)。
操作 2:在文本框中输入 K(1≤K≤n),在标签中输出a(K)的值。
为了提高算法的效率,小明设计了如下算法,以 n=10 为例,如下表所示。
数组下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
元素的值 | 7 | 12 | 3 | 6 | 7 | 11 | 8 | 24 | 9 | 5 |
4)对于操作2,若输入K的值为5,则输出a(5)的值,a(5)的值为该数组元素的值+段标记值,即a(5)=12。程序运行界面如下。请回答下列问题:
(1)若数组元素为“3,2,6,8,7,9,3, 4, 7, 9,6",依次进行以下3次操作后第3段的标记值为 。
操作1:依次输入1, 11,1
操作1:依次输入7,9,2
操作2:输入8
(2)请在划线处填入合适的代码。
Const n = 10
Dim a(1 To n) As Integer
Dim f(1 To n) As Integer 'f数组元素依次表示每段的标记值
Dim bk As Integer ' bk表示每段的元素个数
Function BL(x As Integer) As Integer ' BL函数返回数组元素a(x)的段编号
BL = ①
End Function
Private Sub Form_Load()
'读取数据,并存储到数组a中,代码略
bk = Int(Sqr(n))
End Sub
Private Sub Command1_Click()
Dim L As Integer, R As Integer, T As Integer, i As Integer
L = Val(Text1.Text): R = Val(Text2.Text): T = Val(Text3.Text)
If BL(L) = BL(R) Then
For i = L To R
a(i) = a(i) + T
Next i
Else
For i = ②
a(i) = a(i) + T
Next i
For i = BL(L) + 1 To BL(R) - 1
f(i) = f(i) + T
Next i
For i = (BL(R) - 1) * bk + 1 To R
a(i) = a(i) + T
Next i
End If
End Sub
Private Sub Command2_Click()
Dim K As Integer
K = Val(Text4.Text)
Label5.Caption = "经过一系列操作后,a(" + Str(K) + " )的值为:" + ③
End Sub
六拓展思考答案(1)7 (1 分)
(2)①(x - 1) \ bk + 1 (2 分)
②L To BL(L) * bk (2 分)
③Str(a(K) + f(BL(K))) (2 分)
写在后面为了保证解析的原创性和思维的独特性,我都是独立解题后,先不看答案(除非题目不会做),直接把解析写好,再去看答案。
当然,如果发现参考答案有更好的思路,我还是很乐于学习和借鉴的。同时,由于本人水平有限,解析中难免出现疏漏甚至错误之处,敬请谅解。
无论是赞同还是反对我的看法,都请你给我留言。如果你有新的想法,千万不要憋在心里,请发出来大家一起讨论。让我们相互学习,共同进步!
需要本文word版的,可以加入“选考VB算法解析”知识星球参与讨论和下载文件,“选考VB算法解析”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。
我们专注选考VB算法,感兴趣就一起来!
相关优秀文章:
阅读代码和写更好的代码
最有效的学习方式
选考VB算法解析之2018年11月高考真题卷第16题
选考VB算法解析之2018年11月高考真题卷第17题
选考VB算法解析之2019年4月高考真题卷第16题