回 帖 发 新 帖 刷新版面

主题:大虾帮我改进一下吧

1.[题目]
在N*N的棋盘上(1<=N<=10)填入1,2...N*N共N*N个数,使得任意两个相邻的数之和为素数.
例如:当N=2时,有:
   1  2    其相邻的和为素数的有:
   4  3      1+2,1+4,4+3,2+3
在这里我们约定:左上角的格子里必须放1.

[程序]
CLS
INPUT "Please input N: ", N
IF N < 2 THEN 2
DIM A(N, N), B(N * N)
FOR I = 1 TO N * N: B(I) = I: NEXT I
DO
  FOR I = 1 TO N * N
    X = I \ N + 1: Y = I MOD N
    IF I MOD N = 0 THEN X = X - 1: Y = N
    A(X, Y) = B(I)
  NEXT I: F = 1
  FOR I = 1 TO N
    FOR J = 1 TO N
      IF I < N THEN
        P = A(I, J) + A(I + 1, J)
        GOSUB 10
        IF Q = 0 THEN GOTO 1
      END IF
      IF J < N THEN
        P = A(I, J) + A(I, J + 1)
        GOSUB 10
        GOSUB 10
        IF Q = 0 THEN GOTO 1
      END IF
    NEXT J
  NEXT I
  IF F = 1 THEN
    FOR I = 1 TO N
      FOR J = 1 TO N
        PRINT USING "####"; A(I, J);
      NEXT J: PRINT
    NEXT I: END
  END IF
1 J = N * N: K = N * N
  WHILE B(J) < B(J - 1) AND J > 1: J = J - 1: WEND
  IF J = 1 THEN EXIT DO
  WHILE B(K) < B(J - 1): K = K - 1: WEND
  SWAP B(J - 1), B(K)
  FOR I = J TO N * N - 1
    FOR K = I + 1 TO N * N
      IF B(I) > B(K) THEN SWAP B(I), B(K)
    NEXT K
  NEXT I
LOOP
2 PRINT "NO!"
END
10 Q = 1
   IF P < 2 THEN Q = 0: RETURN
   FOR K = 2 TO SQR(P)
     IF P MOD K = 0 THEN Q = 0: RETURN
   NEXT K
   RETURN

速度特别慢.

2.[题目]
对于正整数N(3<=N<=20),可以画出N阶的回形方阵.如N=7,则方阵为:
1  1  1  1  1  1  1
1  2  2  2  2  2  1
1  2  3  3  3  2  1
1  2  3  4  3  2  1
1  2  3  3  3  2  1
1  2  2  2  2  2  1
1  1  1  1  1  1  1
对于N阶回形矩阵,从左上角出发,每步可向右或向下走一格,走N*2-2步,可以到达右下角.
我们把这样的路径上所有格子中的数值之和,叫做该路径的长度.
本题要求,对于给出的N值,求出N阶回形矩阵有多少路径的长度为素数?
如N=3时,路径长度有
[b]1  1  1[/b]    [b]1  1[/b]  1    [b]1  1[/b]  1
1  2  [b]1[/b]    1  [b]2  1[/b]    1  [b]2[/b]  1
1  1  [b]1[/b]    1  1  [b]1[/b]    1  [b]1  1[/b]
长度=5     长度=6     长度=6

[b]1[/b]  1  1    [b]1[/b]  1  1    [b]1[/b]  1  1
[b]1  2  1[/b]    [b]1  2[/b]  1    [b]1[/b]  2  1
1  1  [b]1[/b]    1  [b]1  1[/b]    [b]1  1  1[/b]
长度=6     长度=6     长度=5

因此说,3阶回形矩阵有2条路径的长度为素数.

[程序]
CLS
INPUT "Please input N: ", N
DIM A(N, N), B(2 * N - 1, 2), C(N, N), D(N * 2 - 1 TO N * (N + 1) / 2)
FOR I = 1 TO (N + 1) \ 2
  FOR J = 1 TO (N + 1) \ 2
    IF I <= J THEN A(I, J) = I ELSE A(I, J) = J
    A(I, N + 1 - J) = A(I, J)
    A(N + 1 - I, J) = A(I, J)
    A(N + 1 - I, N + 1 - J) = A(I, J)
  NEXT J
NEXT I
J = 1: X = 1: Y = 1: S = 1
DO
  F = 1
  DO
    B(J, 1) = X: B(J, 2) = Y: J = J + 1: S = S + A(X, Y)
    IF X = N OR Y = N THEN
      C(X, Y) = 1
      IF X = N THEN Y = Y + 1 ELSE X = X + 1
    ELSE
      C(X, Y) = 2
      Y = Y + 1
    END IF
  LOOP UNTIL J = 2 * N - 1
  IF D(S) = 1 THEN F = 0: GOTO 1
  IF D(S) = 2 THEN 1
  FOR I = 2 TO SQR(S)
    IF S MOD I = 0 THEN F = 0: EXIT FOR
  NEXT I: D(S) = F + 1
1 IF F = 1 AND S <> 1 THEN T = T + 1
  FOR I = J TO 1 STEP -1
    IF C(B(I, 1), B(I, 2)) = 2 THEN EXIT FOR
  NEXT I
  IF I = 0 THEN EXIT DO
  X1 = B(I, 1): Y1 = B(I, 2): C(X1, Y1) = 1
  X = X1 + 1: Y = Y1: J = I + 1: S = 1
  FOR I = 1 TO J - 1
    S = S + A(B(I, 1), B(I, 2))
  NEXT I
LOOP
PRINT "S ="; T
END

N小的时候还好,大的时候速度特别慢.

上面的两题请大虾们帮俺改进一下或是给出一种不同的算法,谢啦~~

回复列表 (共19个回复)

11 楼

分布里我只找到了前n项和倒数三项的规律,
中间那些数值我一直无法找出它们的变化规律.
所以不能用公式的方法去计算.

我又尝试用数组的方法去计算,
结果因为数组的灵活性不够,很快就把空间耗尽了.

又换了字符串来做,但也只能算到 n=15
代码如下:

declare function add$ (a$, b@, c$)
declare function jigo$ (a@, b@)
defcur a-z
m = 15
l = (m + 1) * m / 2
dim shared s$(m, m), n, nm1
n = m
nm1 = (n + 1) / 2

a$ = jigo$(m, m)
cls
for i = 1 to len(a$) step 16
    x = cvc(mid$(a$, i, 8))
    y = cvc(mid$(a$, i + 8, 8))
    print x; y
next
    

function add$ (a$, b, c$)
for i = 1 to len(a$) step 16
    x = cvc(mid$(a$, i, 8)) + b
    y = cvc(mid$(a$, i + 8, 8))
    for j = 1 to len(c$) step 16
        if cvc(mid$(c$, j, 8)) = x then
           mid$(c$, j + 8, 8) = mkc$(cvc(mid$(c$, j + 8, 8)) + y)
           exit for
        end if
    next
    if j > len(c$) then c$ = c$ + mkc$(x) + mkc$(y)
next
add$ = c$
end function

function jigo$ (a, b)
if b > a then swap a, b
if s$(a, b) = "" then
   if b = 1 then
      s$(a, b) = mkc$(a) + mkc$(1)
   else
      p = abs(a - nm1)
      q = abs(b - nm1)
      if q > p then swap p, q
      p = nm1 - p
      s$(a, b) = add$(jigo$((a), (b - 1)), p, s$(a, b))
      s$(a, b) = add$(jigo$((a - 1), (b)), p, s$(a, b))
   end if
end if
jigo$ = s$(a, b)
end function

这已经是用所谓的货币型数据了,
看看结果可以知道,得出的结果有多么的巨大得可怕.
这些值要验证是否质数怕也不是一时刻能办得到的.
我曾经最快的程序算质数算到八位数需时将近一天时间.

所以我怀疑是你会错题意了,我觉得应该是这样子的:
[color=0000FF]
对于给出的N值,求出N阶回形矩阵的所有长度有多少个是素数?
如N=3时,路径长度有
[color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]    [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]  1    [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]  1
1  2  [color=00FF00]1[/color][color=0000FF]    1  [color=00FF00]2[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]    1  [color=00FF00]2[/color][color=0000FF]  1
1  1  [color=00FF00]1[/color][color=0000FF]    1  1  [color=00FF00]1[/color][color=0000FF]    1  [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]
长度=5     长度=6     长度=6

[color=00FF00]1[/color][color=0000FF]  1  1    [color=00FF00]1[/color][color=0000FF]  1  1    [color=00FF00]1[/color][color=0000FF]  1  1
[color=00FF00]1[/color][color=0000FF]  [color=00FF00]2[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]    [color=00FF00]1[/color][color=0000FF]  [color=00FF00]2[/color][color=0000FF]  1    [color=00FF00]1[/color][color=0000FF]  2  1
1  1  [color=00FF00]1[/color][color=0000FF]    1  [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]    [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]  [color=00FF00]1[/color][color=0000FF]
长度=6     长度=6     长度=5

因此说,3阶回形矩阵的长度有5和6
只有1个长度为素数.[/color]

这样一来,题目就变得简单多了.

12 楼

我居然为这些算术题花了很多时间
其实说起来,QB的确没有C的高效和自由灵活方便.
多了一道数值转换的工序.
QB的变长字符串就有那么点意思了.

13 楼

(第一题)
declare function fen@ (a@, b@) 这句错误:它扫黑"@ ("说 Expected: CDECL or ALIAS or ( or end-of-statement 这是怎么回事?请大师指教!?
DEFtype只能是DEFINT DEFSNG DEFDBL DEFLNG DEFSTR "DEFCUR"是什么东东!?
(第二题)
第二题我只是把原题目打了一遍,不是象你说的那样~~

14 楼

对了我还有一题向你求救:

[题目]砖块楼梯
小明有N块砖,用这些小砖块他能摆出各式各样的楼梯。楼梯分成许多台阶,所谓的台阶就是脚能够直接踩踏到的每一个砖块叫做一个台阶。而且这些台阶是按高度递增的顺序从左向右排列的,任意两个台阶的高度都各不相同。每个楼梯至少有两个台阶,并且每个台阶至少有一个小砖块组成。下图分别给出了N = 11和N = 5时的情形。他想知道恰好用这N块砖能够组成多少种不同的楼梯。请你帮小明编写程序求出这个答案。
 N = 11           N = 5
      □         □    □
      □         □  □□
    □□         □  □□
  □□□       □□
□□□□

输入:文件的第一行有一个数M,表示随后的M行中每行有一个整数N。 
输出:依次输出每一个整数N的解。
例如:
输入
1
212

输出
995645335

[程序]
CLS
OPEN "E:\TM6In.in" FOR INPUT AS #1
DIM A(1000): INPUT #1, M
FOR L = 1 TO M
  INPUT #1, N: T = 0
  PRINT "N ="; STR$(N); ":";
  J = 1: S = 0: K = 0
  DO
    K = K + 1: S = S + K
    IF S <= N THEN
      A(J) = K
      IF S = N THEN
        T = T + 1
        S = S - A(J): J = J - 1: S = S - A(J): K = A(J)
      ELSE
        K = A(J): J = J + 1
      END IF
    ELSE
      S = S - K: J = J - 1: S = S - A(J): K = A(J)
    END IF
  LOOP UNTIL J = 0
  PRINT T
NEXT L
END

15 楼

我用的是 QB7.1
有一个新的变量类型 CURRENCY
取值范围是: 

@  Scaled integer     8 bytes           -922337203685477.5808
   (CURRENCY)                           to 922337203685477.5807

后面一题没看懂题目.

16 楼

第二题,我把CURRENCY类型改回长整形了,但最大只能算到 N=17
先把程序发上来,等一下我再把递归改成数组.

declare function add$ (a$, b&, c$)
declare function jigo$ (a&, b&)
deflng a-z
cls
input "n=";m

l = (m + 1) * m / 2
dim shared s$(m, m), n, nm1
n = m
nm1 = (n + 1) / 2

dim z(l)
z(2) = 2
for i = 3 to l step 2
    for j = 1 to i - 1
        if z(j) <> 0 then if i mod z(j) = 0 then exit for
    next
    if j >= i then z(i) = i
next


a$ = jigo$(m, m)
cls
for i = 1 to len(a$) step 8
    x = cvl(mid$(a$, i, 4))
    y = cvl(mid$(a$, i + 4, 4))
    if z(x) = x then sumy = sumy + y
next
print sumy

function add$ (a$, b, c$)
for i = 1 to len(a$) step 8
    x = cvl(mid$(a$, i, 4)) + b
    y = cvl(mid$(a$, i + 4, 4))
    for j = 1 to len(c$) step 8
        if cvl(mid$(c$, j, 4)) = x then
           mid$(c$, j + 4, 4) = mkl$(cvl(mid$(c$, j + 4, 4)) + y)
           exit for
        end if
    next
    if j > len(c$) then c$ = c$ + mkl$(x) + mkl$(y)
next
add$ = c$
end function

function jigo$ (a, b)
if b > a then swap a, b
if s$(a, b) = "" then
   if b = 1 then
      s$(a, b) = mkl$(a) + mkl$(1)
   else
      p = abs(a - nm1)
      q = abs(b - nm1)
      if q > p then swap p, q
      p = nm1 - p
      s$(a, b) = add$(jigo$((a), (b - 1)), p, s$(a, b))
      s$(a, b) = add$(jigo$((a - 1), (b)), p, s$(a, b))
   end if
end if
jigo$ = s$(a, b)
end function

17 楼

我把第二题的程序又改了,
长整形最大只能算到 N=19  改用货币型,现在最大能算到 N=20
如果要更大的值,我也只能算到 N=24,这应该已经是QB的极限了,因为我已经用了很多办法来加大取值的范围和减少空间的占用.有机会的话,再用VB来试试好了.
下面这个程序只能算到 N=20

declare sub addtos (a$, b&, c$)
deflng a-z
cls
input "n=", n
if n < 2 or n > 20 then end
l = (n + 1) * n / 2
dim s$(n, n), z(l)
nm1! = (n + 1) / 2

z(2) = 2
for i = 3 to l step 2
    for j = 1 to i - 1
        if z(j) <> 0 then if i mod z(j) = 0 then exit for
    next
    if j >= i then z(i) = i
next

for i = 1 to n
    for j = 1 to i
        if i = 1 or j = 1 then
           s$(i, j) = mkl$(i * j) + mkl$(1)
        else
           p = nm1! - abs(i - nm1!)
           q = nm1! - abs(j - nm1!)
           if q < p then swap p, q
           addtos s$(i, j - 1), p, s$(i, j)
           if j = i then
              addtos s$(i, j - 1), p, s$(i, j)
           else
              addtos s$(i - 1, j), p, s$(i, j)
           end if
        end if
        if i > 2 and j > 2 then s$(i - 2, j - 2) = ""
next j, i
        
a$ = s$(n, n)
for i = 1 to len(a$) step 8
    x = cvl(mid$(a$, i, 4))
    y = cvl(mid$(a$, i + 4, 4))
    if z(x) = x then sumy@ = sumy@ + y
next
print sumy@

sub addtos (a$, b, c$)
for i = 1 to len(a$) step 8
    x = cvl(mid$(a$, i, 4)) + b
    y = cvl(mid$(a$, i + 4, 4))
    for j = 1 to len(c$) step 8
        if cvl(mid$(c$, j, 4)) = x then
           mid$(c$, j + 4, 4) = mkl$(cvl(mid$(c$, j + 4, 4)) + y)
           exit for
        end if
    next
    if j > len(c$) then c$ = c$ + mkl$(x) + mkl$(y)
next
end sub

再下面这个程序可以算到 N=23, 再下去就没必要了.
declare sub addnext (i@, j@, c$)
declare sub addtos (a$, b@, c$)
defcur a-z
cls
input "n=", n
l = (n + 1) * n / 2
dim shared s$(n, n), z(l), m, nm1!
m = n
nm1! = (n + 1) / 2

z(2) = 2
for i = 3 to l step 2
    for j = 1 to i - 1
        if z(j) <> 0 then if i mod z(j) = 0 then exit for
    next
    if j >= i then z(i) = i
next

s$(1, 1) = mkc$(1) + mkc$(1)
for i = 1 to n
    for j = 1 to i
        if j = n then exit for
        addnext (i + 1), (j), (s$(i, j))
        addnext (i), (j + 1), (s$(i, j))
        s$(i, j) = ""
next j, i
        
a$ = s$(n, n)
for i = 1 to len(a$) step 16
    x = cvc(mid$(a$, i, 8))
    y = cvc(mid$(a$, i + 8, 8))
    print x; y,
    if z(x) = x then sumy@ = sumy@ + y
next
print
print sumy@

sub addnext (i, j, c$)
    if j > i or i > m or j > m then exit sub
    p = nm1! - abs(i - nm1!)
    q = nm1! - abs(j - nm1!)
    if q < p then swap p, q
    addtos c$, p, s$(i, j)
    if j = i then addtos c$, p, s$(i, j)
end sub

sub addtos (a$, b, c$)
for i = 1 to len(a$) step 16
    x = cvc(mid$(a$, i, 8)) + b
    y = cvc(mid$(a$, i + 8, 8))
    for j = 1 to len(c$) step 16
        if cvc(mid$(c$, j, 8)) = x then
           mid$(c$, j + 8, 8) = mkc$(cvc(mid$(c$, j + 8, 8)) + y)
           exit for
        end if
    next
    if j > len(c$) then c$ = c$ + mkc$(x) + mkc$(y)
next
end sub

可能是我自视过高,
但我花了时间不少,
所以我很有兴趣看看标准答案是怎样得来的.
或者有更简单的公式我不懂得用上.

18 楼

NO!

19 楼

严重鄙视小小tqw来捣乱

我来回复

您尚未登录,请登录后再回复。点此登录或注册