Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 2053|回复: 2

[已解决]VBA实现四阶幻方素数

[复制链接]
发表于 2016-4-20 16:50 | 显示全部楼层 |阅读模式

VBA实现四阶幻方素数

用1到16构成一个四阶幻方,要求任意相邻两个方格中的数字之和均为素数




最佳答案
2016-4-23 16:21
我的递归算法比你至少快1倍。

是在上次圆圈素数的基础上改的。
  1. Dim a&(), b(), c() As Boolean, k&, n&, cnt&
  2. Sub 矩阵相邻数相加为素数的排列计算()
  3.     Dim i&, tms#
  4.     [a:d] = ""
  5.     tms = Timer
  6.    
  7.     n = 8 '实际范围为1-16
  8.     ReDim a(3, n - 1), b(3, 3)
  9.     For i = 1 To n
  10.         a(2, i - 1) = i * 2: a(3, i - 1) = i * 2 - 1
  11.     Next
  12.     c = GetPrime(4 * n - 1)
  13.    
  14.     k = 0: cnt = 0: Call dgPL2(1, 0): Call dgPL2(0, 0)
  15.     MsgBox Format(Timer - tms, "0.000s ") & k & "/" & cnt
  16. End Sub
  17. Sub dgPL2(i&, t&)
  18.     Dim i1&, j1&, j&, r&, f As Boolean
  19.     cnt = cnt + 1
  20.     If t = 2 * n Then Cells(k * 5 + 1, 1).Resize(4, 4) = b: k = k + 1
  21.     i1 = t \ 4: j1 = t Mod 4
  22.     For j = 0 To n - 1
  23.         If a(i, j) = 0 Then
  24.             f = False: r = a(i + 2, j)
  25.             If i1 = 0 Then f = True Else If c(b(i1 - 1, j1) + r) Then f = True
  26.             If f Then If j1 Then f = c(b(i1, j1 - 1) + r)
  27.             If f Then
  28.                 a(i, j) = 1: b(i1, j1) = r
  29.                 Call dgPL2(IIf(j1 = 3, i, IIf(i, 0, 1)), t + 1)
  30.                 a(i, j) = 0: b(i1, j1) = ""
  31.             End If
  32.         End If
  33.     Next
  34. End Sub
  35. Function GetPrime(n&) '计算素数数列
  36.     Dim a&(), b() As Boolean, i&, j&, k&, m&, s&
  37.     m = n \ 2: ReDim a&(m), b(3 To n) As Boolean
  38.     For i = 1 To Sqr(n) \ 2
  39.         If a(i) = 0 Then
  40.             s = i * 2 + 1: b(s) = True: k = k + 1: a(k) = s
  41.             For j = (i * 3 + 1) To m Step s
  42.                 a(j) = 1
  43.             Next
  44.         End If
  45.     Next
  46.     For i = (a(k) + 1) / 2 To m
  47.         If a(i) = 0 Then s = i * 2 + 1: b(s) = True ': k = k + 1: a(k) = s
  48.     Next
  49.     GetPrime = b
  50. End Function
复制代码
excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
 楼主| 发表于 2016-4-21 08:41 | 显示全部楼层
来一个


Dim arr%(3, 3)
Sub s()
    Dim brr(15)
    For i = 1 To 16
        brr(i - 1) = i
    Next
    p brr, 0, 0
End Sub
Function ss(ByVal n%) As Boolean
    Select Case n
        Case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31
            ss = True
        Case Else
            ss = False
    End Select
End Function
Sub p(brr, x, y)
    If x = 3 And y = 3 Then
        arr(3, 3) = brr(0)
        If ss(arr(2, 3) + arr(3, 3)) And ss(arr(3, 2) + arr(3, 3)) Then o
    Else
        x1 = (x + 1) Mod 4
        y1 = y
        If x1 = 0 Then y1 = y1 + 1
        k = UBound(brr) - 1
        ReDim crr(k)
        For i = 0 To k
        crr(i) = brr(i + 1)
        Next
        For i = 0 To k + 1
            arr(x, y) = brr(i)
            If i > 0 Then crr(i - 1) = brr(i - 1)
            If x > 0 Then
                If Not ss(arr(x, y) + arr(x - 1, y)) Then GoTo 1
            End If
            If y > 0 Then
                If Not ss(arr(x, y) + arr(x, y - 1)) Then GoTo 1
            End If
            p crr, x1, y1
1:      Next
    End If
End Sub
Sub o()
    Static x&
    x = x + 5
    Cells(x, 1).Resize(4, 4) = arr
End Sub
回复

使用道具 举报

发表于 2016-4-23 16:21 | 显示全部楼层    本楼为最佳答案   
我的递归算法比你至少快1倍。

是在上次圆圈素数的基础上改的。
  1. Dim a&(), b(), c() As Boolean, k&, n&, cnt&
  2. Sub 矩阵相邻数相加为素数的排列计算()
  3.     Dim i&, tms#
  4.     [a:d] = ""
  5.     tms = Timer
  6.    
  7.     n = 8 '实际范围为1-16
  8.     ReDim a(3, n - 1), b(3, 3)
  9.     For i = 1 To n
  10.         a(2, i - 1) = i * 2: a(3, i - 1) = i * 2 - 1
  11.     Next
  12.     c = GetPrime(4 * n - 1)
  13.    
  14.     k = 0: cnt = 0: Call dgPL2(1, 0): Call dgPL2(0, 0)
  15.     MsgBox Format(Timer - tms, "0.000s ") & k & "/" & cnt
  16. End Sub
  17. Sub dgPL2(i&, t&)
  18.     Dim i1&, j1&, j&, r&, f As Boolean
  19.     cnt = cnt + 1
  20.     If t = 2 * n Then Cells(k * 5 + 1, 1).Resize(4, 4) = b: k = k + 1
  21.     i1 = t \ 4: j1 = t Mod 4
  22.     For j = 0 To n - 1
  23.         If a(i, j) = 0 Then
  24.             f = False: r = a(i + 2, j)
  25.             If i1 = 0 Then f = True Else If c(b(i1 - 1, j1) + r) Then f = True
  26.             If f Then If j1 Then f = c(b(i1, j1 - 1) + r)
  27.             If f Then
  28.                 a(i, j) = 1: b(i1, j1) = r
  29.                 Call dgPL2(IIf(j1 = 3, i, IIf(i, 0, 1)), t + 1)
  30.                 a(i, j) = 0: b(i1, j1) = ""
  31.             End If
  32.         End If
  33.     Next
  34. End Sub
  35. Function GetPrime(n&) '计算素数数列
  36.     Dim a&(), b() As Boolean, i&, j&, k&, m&, s&
  37.     m = n \ 2: ReDim a&(m), b(3 To n) As Boolean
  38.     For i = 1 To Sqr(n) \ 2
  39.         If a(i) = 0 Then
  40.             s = i * 2 + 1: b(s) = True: k = k + 1: a(k) = s
  41.             For j = (i * 3 + 1) To m Step s
  42.                 a(j) = 1
  43.             Next
  44.         End If
  45.     Next
  46.     For i = (a(k) + 1) / 2 To m
  47.         If a(i) = 0 Then s = i * 2 + 1: b(s) = True ': k = k + 1: a(k) = s
  48.     Next
  49.     GetPrime = b
  50. End Function
复制代码

评分

参与人数 1 +9 收起 理由
vbyou127 + 9 来学习

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-24 08:35 , Processed in 0.249863 second(s), 11 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表