Đâu có gì ghê gớm đâu. Bạn chỉ cần phân tích đề 1 chút thì sẽ có hướng làm thôi. Mấy con số 1234 hay 98765 kia thì khoan vội quan tâm đã. Bạn thấy 1 số có 5 chữ số khác nhau thì cứ xem đó như 1 số có 5 chữ số thôi vậy nó phải nằm trong [1000,99999] đúng không?hic. em đọc mãi mà vẫn chưa hiểu rõ về code này. bác Po_Pikachu giải thích một ít đi. Cho bọn em còn học hỏi và nâng cao thuật toán tý.
cảm ơn bác nhìu nhìu
For i = 1000 To 99999
For j = 1000 To 99999
If i / j = 9 Then
M = Format(i, "00000") & Format(j, "00000")
For x = 2 To 10
If InStr(x, M, Mid(M, x - 1, 1)) = 0 Then
???
Else
???
End If
Next
If ??? Then
Cells(k, "A") = i
Cells(k, "B") = j
End If
End If
Next
Next
Thấy thời gian rút đáng kể; Đó là nhờ các dòng lệnh được đánh số thêm vào:
Mã:Option Explicit [B]Sub chay01()[/B] Dim M As String, jJ As Byte, Ww As Long, Zz As Long, Ff As Byte, JF As Byte Dim Timer_ As Double jJ = 1: Timer_ = Timer For Ww = 11106 To 98765 1 If Ww \ 9 = Ww / 9 Then For Zz = 1234 To 10974 2 If Zz \ 9 = Zz / 9 Then If Ww / Zz = 9 Then [D1] = Ww M = Format(Ww, "00000") & Format(Zz, "00000") For Ff = 2 To 10 If InStr(Ff, M, Mid(M, Ff - 1, 1)) = 0 Then JF = 1 Else JF = 0: Exit For End If Next If JF = 1 Then Cells(jJ, "A") = Ww: Cells(jJ, "B") = Zz jJ = jJ + 1 End If End If 21 End If Next 11 End If Next Cells(65500, "D").End(xlUp).Offset(1).Value = Timer - Timer_ [B]End Sub[/B]
Thời gian theo máy của mình rút từ 77.891 gy còn 9.359 gy Nhờ vào tính chia hết của tử số cũng như mẫu số
Sub Thuong9()
Dim M As String, k As Byte, i As Long, j As Long, x As Byte, d As Byte
Dim Timer_ As Double
k = 1: Timer_ = Timer
For i = 1234 To 98765
If i Mod 9 = 0 Then
M = Format(i, "00000") & Format(i / 9, "00000")
d = 0
For x = 2 To 10
If InStr(x, M, Mid(M, x - 1, 1)) = 0 Then
d = d + 1
Else
Exit For
End If
Next
If d = 9 Then
Cells(k, "A") = i
Cells(k, "B") = i / 9
k = k + 1
End If
End If
Next
Range("E1") = Timer - Timer_
MsgBox (Timer - Timer_)
End Sub
PHP:Sub thuonglt() Dim i As Long, j As Long, x As Long, d As Byte, dl As String, M As String, iCol As Long, test As String Dim Timer_ As Double dl = "1-2-3-4-5-6-7-8": Timer_ = Timer Range("A1", Cells(65000, UBound(Split(dl, "-")) + 1)).ClearContents For i = 0 To UBound(Split(dl, "-")) Cells(1, i + 1) = Split(dl, "-")(i) Next For i = 1234 To 98765 test = kiem(i, dl) For j = 0 To UBound(Split(test, "-")) If test = "" Then Exit For iCol = Val(Split(test, "-")(j)) M = Format(i, "00000") & Format(i / iCol, "00000") For x = 2 To 10 If InStr(x, M, Mid(M, x - 1, 1)) = 0 Then d = 1 Else d = 0 Exit For End If Next If d = 1 Then Cells(65000, WorksheetFunction.Match(iCol, Range("A1", Cells(1, UBound(Split(dl, "-")) + 1)), 0)).End(xlUp).Offset(1) = i & "-" & i / iCol End If Next Next [A2].Select MsgBox (Timer - Timer_) End Sub
PHP:Function kiem(so As Long, dl As String) Dim temp As String For i = 1 To UBound(Split(dl, "-")) If so Mod Val(Split(dl, "-")(i)) = 0 Then temp = temp & Split(dl, "-")(i) & " " End If Next kiem = Replace(Trim(temp), " ", "-") End Function
Sub Main(NumLength As Long, qt As Long)
Dim i As Long, j As Long, Tmp As String, Arr()
If NumLength > 5 Then Exit Sub
i = 10 ^ (NumLength - 1)
Do
Tmp = i & (i * qt)
If CheckUnique(Tmp) Then
ReDim Preserve Arr(j)
Arr(j) = i * qt & " = " & i & " * " & qt
j = j + 1
End If
i = i + 1
Loop Until i * qt > 10 ^ NumLength - 1
If j Then MsgBox Join(Arr, vbLf)
End Sub
Function CheckUnique(Num As String) As Boolean
Dim i As Long, Check As Boolean
Do
Check = (Len(Num) - Len(Replace(Num, i, "")) > 1)
i = i + 1
Loop Until Check Or i = 10
CheckUnique = Not Check
End Function
Sub Test()
Main 5, 9
End Sub
F=0 cũng là nghiệm chớ anh?Main 5, 9 có nghĩa là tìm các cặp số có độ dài chuổi = 5, có thưong số của phép chia giửa 2 số = 9
Thử nghiệm này cho ra 3 nghiệm
Đã gọi là số có 5 chữ số thì không có cái vụ số 0 nằm ở đầu nha!
Nếu F = 0 bạn gọi số chia là số có mấy chữ số?F=0 cũng là nghiệm chớ anh?
Sub Main(NumLength As Long, qt As Long)
Dim i As Long, j As Long, Tmp As String, Arr(60000, 1)
If NumLength > 5 Then Exit Sub
i = WorksheetFunction.RoundUp((10 ^ (NumLength - 1) / qt), 0)
Do
Tmp = i * qt & Format(i, String(NumLength, "0"))
If CheckUnique(Tmp) Then
Arr(j, 0) = i * qt
Arr(j, 1) = i
j = j + 1
End If
i = i + 1 - (((i + 1) Mod 10) = 0)
Loop Until i * qt > 10 ^ NumLength - 1
If j Then Range("A1:B1").Resize(j) = Arr
End Sub
Function CheckUnique(Num As String) As Boolean
Dim i As Long, Check As Boolean
Do
Check = (Len(Num) - Len(Replace(Num, i, "")) > 1)
i = i + 1
Loop Until Check Or i = 10
CheckUnique = Not Check
End Function
Sub Test()
Main 5, 9
End Sub
Bài toán tổng quát thì khỏi cần xét mấy vụ này!Các cặp số đó có những tính chất sau:
Để có kết quả là 9 thì cả hai số sẽ fải chia hết cho 9;
Nếu thương của cặp số là số chẵn thì số bị chia fải là số chẵn;
Nếu thương là lẽ, thì hai số cũng fải là lẽ.
Ta đưa các tính chất này vô, chắc sẽ giảm hao fí thời gian cho máy!
Chuổi "123456789" qua phép hoán vị ta được 362880 phần tử ---> Cái này em có thể tìm được!Cho 1 dãy số gồm 9 số khác nhau hoàn toàn & không có số không (ABCDEFGHI)
Đem số này chia cho số n sẽ fải nhận được 1 số như vậy, chỉ đảo vị trí giữa chúng
Hãy tìm các số ấy, khi n= 2, 4, 5, 7, 8
Dim n As Long, Arr(1 To 362880, 1 To 1)
Sub GetString()
Dim Num As String
Num = "123456789"
n = 1
GetPermu "", Num
Range("A1").Resize(n - 1) = Arr
End Sub
Sub GetPermu(x As String, y As String)
Dim i As Long, j As Long
j = Len(y)
If j < 2 Then
Arr(n, 1) = x & y
n = n + 1
Else
For i = 1 To j
GetPermu x & Mid(y, i, 1), Left(y, i - 1) & Right(y, j - i)
Next
End If
End Sub
Hay quá, cám ơn ndu, đang tìm cách tạo tổ hợp chập.Chuổi "123456789" qua phép hoán vị ta được 362880 phần tử ---> Cái này em có thể tìm được!
Tuy nhiên để tìm số thỏa mản yêu cầu mà sư phụ đưa ở trên thì... em chẳng tìm thấy số nào cả
PHP:Dim n As Long, Arr(1 To 362880, 1 To 1)
PHP:Sub GetString() Dim Num As String Num = "123456789" n = 1 GetPermu "", Num Range("A1").Resize(n - 1) = Arr End Sub
Code trên liệt kê tất cả các phần tử qua phép hoán vị ---> Các bạn tìm thử xem trong số đó có cái nào phù hợp yêu cầu không? (tôi bó tay)PHP:Sub GetPermu(x As String, y As String) Dim i As Long, j As Long j = Len(y) If j < 2 Then Arr(n, 1) = x & y n = n + 1 Else For i = 1 To j GetPermu x & Mid(y, i, 1), Left(y, i - 1) & Right(y, j - i) Next End If End Sub
Dùng Excel 2007 nha!
Với N=8Chuổi "123456789" qua phép hoán vị ta được 362880 phần tử ---> Cái này em có thể tìm được!
Tuy nhiên để tìm số thỏa mản yêu cầu mà sư phụ đưa ở trên thì... em chẳng tìm thấy số nào cả
PHP:Dim n As Long, Arr(1 To 362880, 1 To 1)
PHP:Sub GetString() Dim Num As String Num = "123456789" n = 1 GetPermu "", Num Range("A1").Resize(n - 1) = Arr End Sub
Code trên liệt kê tất cả các phần tử qua phép hoán vị ---> Các bạn tìm thử xem trong số đó có cái nào phù hợp yêu cầu không? (tôi bó tay)PHP:Sub GetPermu(x As String, y As String) Dim i As Long, j As Long j = Len(y) If j < 2 Then Arr(n, 1) = x & y n = n + 1 Else For i = 1 To j GetPermu x & Mid(y, i, 1), Left(y, i - 1) & Right(y, j - i) Next End If End Sub
Dùng Excel 2007 nha!
For Jj = 987654328 To 987654312 Step -8
. . . . .
Next Jj
Giải thuật này tôi đã áp dụng cho bài số #17, nhưng ở đây có mấy chỗ tôi thấy chưa hợp lý lắm.Thực ra bài toán đó cần biện luận trước, như sau:
Số nhỏ nhất trong đám là 123456789 (Min) & số lớn nhất không thể khác 987654321 (Max)
Giải trường hợp N=8:
Số lớn nhất có thể để thỏa điều kiện nhân với 8 bé hơn Max sẽ là Int(Max/8)+1. Bằng trang tính excel ta biết số đó là 123456791. Vậy tà từ Min đến số này có hơn 100 số chứ mấy!
Nhưng theo mình, cách giải sẽ ngược lại:
Ta fải tìm số lớn hơn Max gần nhất chia hết cho 8, đó là 987654328 (=FLOOR(987654321,8) + 8)
Tiếp đến ta tìm số nhỏ nhất để làm số bị nhân; Số đó sẽ là =FLOOR(123456789*8,8) :=987654312
Ô là là, vòng lặp của chúng ta giảm đáng kể rồi còn gì!
Nhưng chưa hết; Nếu ta biết rằng chỉ những con số chia hết cho 8 mới là đáp án mà thôi
Vậy là vòng lặp ta có dạng
PHP:For Jj = 987654328 To 987654312 Step -8 . . . . . Next Jj
Mình cho rằng đến giờ, cách này là tiết kiệm thời gian nhất.
Xin ý kiến các bạn xa gần.
Đúng là em bị mắc lừaÀ ha, NDU dính mẹo lão già rồi
Cái từ "đảo' ở đây em hiểu là: 123 sau khi "đảo" sẽ thành 321... Ai ngờ... chỉ đảo vị trí giữa chúng...
Dim n As Long, Arr(1 To 362880, 1 To 2) As Long
Sub Test()
Dim Num As String, qt As Long, TG As Double
TG = Timer
Range("A:B").ClearContents
Num = "123456789": qt = Range("G1").Value
n = 1
Main "", Num, qt
If n > 1 Then Range("A1").Resize(n - 1, 2).Value = Arr
MsgBox Timer - TG
End Sub
Sub Main(x As String, y As String, qt As Long)
Dim i As Long, j As Long, Tmp
j = Len(y)
If j < 2 Then
Tmp = x & y
If InStr(Tmp * qt, "0") = 0 Then
If CheckUnique(Tmp * qt) Then
Arr(n, 1) = Tmp
Arr(n, 2) = Tmp * qt
n = n + 1
End If
End If
Else
For i = 1 To j
Main x & Mid(y, i, 1), Left(y, i - 1) & Right(y, j - i), qt
Next
End If
End Sub
Function CheckUnique(Num As String) As Boolean
Dim i As Long, Check As Boolean
Do
Check = (Len(Num) - Len(Replace(Num, i, "")) > 1)
i = i + 1
Loop Until Check Or i = 10
CheckUnique = Not Check
End Function
Dim n As Long, Arr(1 To 362880, 1 To 2) As Long, ChkTotal As Long
Sub Test()
Dim Num As String, qt As Long, TG As Double
TG = Timer
Range("A:B").ClearContents
Erase Arr
Num = "123456789": qt = Range("G1").Value
n = 1: ChkTotal = WorksheetFunction.Fact(Len(Num)) / qt
Main "", Num, qt
If n > 1 Then Range("A1").Resize(n - 1, 2).Value = Arr
MsgBox Timer - TG
End Sub
Sub Main(x As String, y As String, qt As Long)
Dim i As Long, j As Long, Tmp
j = Len(y)
If ChkTotal = 0 Then Exit Sub
If j < 2 Then
ChkTotal = ChkTotal - 1
Tmp = x & y
If InStr(Tmp * qt, "0") = 0 Then
If CheckUnique(Tmp * qt) Then
Arr(n, 1) = Tmp
Arr(n, 2) = Tmp * qt
n = n + 1
End If
End If
Else
For i = 1 To j
Main x & Mid(y, i, 1), Left(y, i - 1) & Right(y, j - i), qt
Next
End If
End Sub