2018年8月11日 星期六

商競程式104模_解題記錄

試題連結 (商業類技藝技賽_104年_程式設計_模擬題)  2018/8/18完成
2018/8/30 更新 p11

用VB10寫在Form_Load,讀檔統一如下,然後呼叫fxx,每題讀檔就不重複


讀檔寫檔

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Hide()
        FileOpen(1, "in1.txt", 1)
        FileOpen(2, "in2.txt", 1)
        FileOpen(3, "out.txt", 2)
        For fn = 1 To 2
            If fn = 2 Then PrintLine(3)
            Dim n As Short = LineInput(fn)
            For k = 1 To n
                Dim s As String = LineInput(fn)
                PrintLine(3, fxx(s))
            Next
        Next
        End
    End Sub
   ...
   每一題 解題部份
   Function fxx( s as ... ) as ...
   ...
End Class

P11 質因數分解
x質因數分解, x<65536 ,先建 sqrt(65535)之內的質數表 pr(0)=2,~ pr(53)=251x被pr(i)整除的個數,>0才印,直到 x =1 或質數用完 x<>1則只有1次方
建質數表,所以在讀檔前呼叫Gen_Pr()  產生 Pr()質數表
    Dim pr(60) As Integer '質數表 54個: 最大251
   Dim pcnt As Integer ' 個數

    Function fxx(ByVal s As String) As String
        Dim x As Integer = s
        fxx = ""
        For i = 0 To pcnt - 1
            If x Mod pr(i) = 0 Then
                Dim cnt As Integer = 0
                Do While x Mod pr(i) = 0
                    cnt += 1
                    x \= pr(i)
                Loop
                If fxx <> "" Then fxx &= " "
                fxx &= pr(i) & "^" & cnt
                If x = 1 Then Exit For
            End If
        Next
        If x > 1 Then
            If fxx <> "" Then fxx &= " "
            fxx &= ( x & "^1" )  '8/30更新, 因少 ^1
        End If
    End Function

    Sub Gen_pr()
        pr(0) = 2 : pcnt = 1
        For k = 3 To 255 Step 2
            If isp(k) Then
                pr(pcnt) = k
                pcnt += 1
            End If
        Next
        ' Return pcnt & " , " & pr(pcnt - 1)
    End Sub

    Function isp(ByVal k As Integer) As Boolean
        If k < 2 Then Return False
        For i = 2 To Math.Sqrt(k)
            If k Mod i = 0 Then Return False
        Next
        Return True
    End Function


P12 N!尾0個數
2*5才會有0,5比2少,只要算5的個數即可

    Function fxx(ByVal s As String) As String
        Dim x As Integer = s
        Dim cnt As Integer = 0
        For i = 5 To x Step 5
            Dim k As Integer = i
            Do While k Mod 5 = 0
                cnt += 1
                k \= 5
            Loop
        Next
        Return cnt
    End Function


P21 計程車費


   Function fxx(ByVal s As String) As String
        Dim k As Integer = s * 1000  '所有的數乘 1000化成公尺
        Dim p = 85  '一上車 85元
        k -= 1500  '可走 1500公尺
        p += ((k + 249) \ 250) * 5 '每 250 公尺 5 元
        Return p
    End Function

P22 迴文


   Function fxx(ByVal s As String) As String
        Dim k As Integer = s.Length
        For j = 1 To k \ 2
            If Mid(s, j, 1) <> Mid(s, k + 1 - j, 1) Then Return "N"
        Next
        Return "Y"
    End Function



P31 是否為樹

同 103 年模擬題P31
   Const MaxN As Integer = 20 '編號 0~20
    Dim adj(MaxN, MaxN) As Boolean '相鄰矩陣
    Dim nds(MaxN) As Boolean '是否為節點
    Dim vst(MaxN) As Boolean '是否訪過
    Sub dfs(ByVal u As Integer) '由 u深訪
        vst(u) = True
        For v = 0 To MaxN
            If adj(u, v) And Not vst(v) Then dfs(v) '相鄰且 v 未訪過
        Next
    End Sub
    Function fxx(ByVal s As String) As String
        s = Trim(s) : ttrim(s, "  ", " ") : ttrim(s, ", ", ",") : ttrim(s, " ,", ",")
        Dim st As Integer ' 起點
        Dim egs() = s.Split(" ")  '邊
        Dim egcnt As Integer = egs.Length  '邊數
        Array.Clear(adj, 0, (MaxN + 1) * (MaxN + 1))
        Array.Clear(nds, 0, MaxN + 1)
         For i = 0 To UBound(egs)
            Dim xy() = egs(i).Split(",") '分成 x,y
            Dim x As Integer = xy(0), y As Integer = xy(1)
            adj(x, y) = True : adj(y, x) = True
            nds(x) = True : nds(y) = True
            st = x
        Next
        Dim ndcnt As Integer = 0  '節點數
        For i = 0 To MaxN
            If nds(i) Then ndcnt += 1
        Next
         If ndcnt <> egcnt + 1 Then Return "F" '點、邊的數不符 樹的規定
        Array.Clear(vst, 0, MaxN + 1)
        dfs(st)
        For i = 0 To MaxN  '是節點,但未訪過,不連通就不是樹
            If nds(i) And Not vst(i) Then Return "F"
        Next
        Return "T"
    End Function


    Sub ttrim(ByRef s As String, ByVal a As String, ByVal b As String)
        Do While (InStr(s, a) > 0)
            s = s.Replace(a, b)
        Loop
    End Sub
P32 二元搜尋樹高
用陣列模擬左鏈及右鏈
因每個檔案只有一組資料,n是節點數,每點一列,在讀檔時一次讀入a(),再給fxx用
  ...
           Dim n As Integer = LineInput(fn)
            For k = 0 To n - 1
                a(k) = LineInput(fn)
                lt(k) = -1 : rt(k) = -1
            Next
            PrintLine(3, fxx(n))
  ...
   Dim a(30), lt(30), rt(30) As Integer   '節點值、左鏈、右鏈

    Function fxx(ByVal n As Integer) As String
        ' n節點數 :最多 30個節點 a()資料、 lt()左鏈、 rt()
        Dim p, pp, h As Integer '目前位置、父、高
        Dim mh As Integer = 0   '高度
        For i = 1 To n - 1
            p = 0 : pp = 0 : h = 0
            Do Until p = -1 '走到 末端,插入點
                pp = p : h += 1
                If a(i) > a(p) Then '大:往右
                    p = rt(p)
                ElseIf a(i) < a(p) Then '小:往左
                    p = lt(p)
                End If
            Loop
            If a(i) > a(pp) Then '父節點的右樹
                rt(pp) = i
            ElseIf a(i) < a(pp) Then '父節點的左樹
                lt(pp) = i
            End If
            If h > mh Then mh = h
        Next
        fxx = mh
    End Function


P41 加減問題

只有三個數,2^3八種 + - 組合,用 8*3的陣列存 -1及1 ,八種各跑1次即可
可直接打表 pm()={}八種組合,也可以跑Gen_Pm產生{在讀檔前呼叫一次}

   'Dim pm(,) As Integer = {{-1, -1, -1}, {-1, -1, 1}, {-1, 1, -1}, {-1, 1, 1}, {1, -1, -1}, {1, -1, 1}, {1, 1, -1}, {1, 1, 1}}
    Dim pm(31, 4) As Integer '假設有 3個數、 4個數、 5個數 三種情形,所以最多 2^5=32種正負狀態
    Sub Gen_pm(ByVal n As Integer)
        For i = 0 To 2 ^ n - 1
            Dim x = i
            For j = 0 To n - 1
                pm(i, j) = IIf(x Mod 2 = 0, -1, 1)
                x \= 2
                '  Debug.Print(i & "," & j & ":" & pm(i, j))
            Next
        Next
    End Sub
    Function fxx(ByVal s As String) As String
        Dim dat() = s.Split(" ")
        Dim a(2) As Integer
        a(0) = dat(0) : a(1) = dat(1) : a(2) = dat(2)
        For j = 0 To 7
            If a(0) * pm(j, 0) + a(1) * pm(j, 1) + a(2) * pm(j, 2) = 0 Then Return "T"
        Next
        Return "F"
    End Function

P42 數字反轉後相加
     ' 使用 Strings.StrReverse 函式
   Function fxx(ByVal s As String) As String
        Dim dat() = s.Split(",")
        Dim a As Integer = Strings.StrReverse(dat(0))
        Dim b As Integer = Strings.StrReverse(dat(1))
        Dim sum As Integer = Strings.StrReverse(a + b)
        Return sum  ' Strings.StrReverse(a + b)  X:若未存入整數,字串的前導0仍會保留
    End Function

 ' 解法2:使用 自訂函式 Rev
   Function Rev(ByVal k As Integer) As Integer
        Rev = 0
        Do While k > 0
            Rev = Rev * 10 + k Mod 10
            k \= 10
        Loop
    End Function
    Function fxx2(ByVal s As String) As String
        Dim dat() = s.Split(",")
        Dim n0 As Integer = dat(0)
        Dim n1 As Integer = dat(1)
        Return Rev(Rev(n0) + Rev(n1))
    End Function







  

0 意見:

張貼留言