所以你需要找到第一个有超过500个除数的三角形数。我找到了一种找到主要因子并将指数倍增的工作方法,但这需要很长时间。我怎样才能加快速度?
Function divisors(ByVal c As Long) As Integer
Dim j, k As Integer
Dim d As Long = c
Dim factors As New List(Of Integer)
For i As Long = 2 To c / 2 + 1
If d Mod i = 0 Then
If i Mod 2 = 0 And i <> 2 Then
i = i / 2
End If
factors.Insert(k, i)
d = d / i
i = 2
k += 1
End If
Next
j = 1
For i As Integer = 0 To factors.Count - 1
j = j * factors(i)
Next
If j <> c Then
factors.Add(2)
End If
factors.Add(factors.Max + 1)
factors.Sort()
Dim count, num1, totfactor As Integer
Dim totfactors As New List(Of Integer)
For Each num As Integer In factors
If num1 <> num Then
totfactor = count
If totfactor <> 0 Then totfactors.Add(totfactor)
totfactor = 0
End If
If num1 <> num Then count = 0
For i As Integer = 0 To c
If num = i Then
count += 1
Exit For
End If
Next
num1 = num
Next
Dim total As Integer = 1
For Each num As Integer In totfactors
total = total * (num + 1)
Next
Return total
End Function
Sub Main()
Dim number As Long = 153
Dim pos As Integer = 18
Do
number = number + pos
Console.WriteLine("number:" & number & " divisors:" & divisors(number))
pos += 1
Loop Until divisors(number) > 500
End Sub
答案 0 :(得分:1)
Dim j, k As Integer
Dim d As Long = c
Dim factors As New List(Of Integer)
For i As Long = 2 To c / 2 + 1
If d Mod i = 0 Then
If i Mod 2 = 0 And i <> 2 Then
i = i / 2
End If
factors.Insert(k, i)
d = d / i
i = 2
k += 1
End If
Next
factors.Insert(k, i)
后面跟着k += 1
,所以这是写factors.Add(i)
的漫长道路。删除k
,在您需要之前不要声明j
。
Dim d As Long = c
Dim factors As New List(Of Integer)
For i As Long = 2 To c / 2 + 1
If d Mod i = 0 Then
If i Mod 2 = 0 And i <> 2 Then
i = i / 2
End If
factors.Add(i)
d = d / i
i = 2
End If
Next
所有这些/
都是浮点除法。使用\
进行整数除法。转过Option Strict On
。另外,简写,因为它很好。在i = 2
末尾设置For
并将i
作为其循环变量也不会执行任何操作,因此请将其删除。
Dim d As Long = c
Dim factors As New List(Of Integer)
For i As Long = 2 To c \ 2 + 1
If d Mod i = 0 Then
If i Mod 2 = 0 And i <> 2 Then
i \= 2
End If
factors.Add(i)
d \= i
End If
Next
我想最内层的If
已被添加,因为您的代码没有获得素数因素,但这不是修复该错误的方法。暂时删除它。
Dim d As Long = c
Dim factors As New List(Of Integer)
For i As Long = 2 To c \ 2 + 1
If d Mod i = 0 Then
factors.Add(i)
d \= i
End If
Next
好的,现在我们已经陷入了获得素数因素(d \= i
)和获得所有除数之间的中间位置。继续使用您的原始素因子计划:由于素数因子可以出现多次,因此您需要在分割数字时保持循环。
Dim d As Long = c
Dim factors As New List(Of Integer)
For i As Long = 2 To c \ 2 + 1
While d Mod i = 0
d \= i
factors.Add(i)
End While
Next
现在外循环可以提前停止很多次。
Dim d As Long = c
Dim i As Long = 2
Dim factors As New List(Of Integer)
While d >= i
While d Mod i = 0
d \= i
factors.Add(i)
End While
i += 1
End While
您还可以使用i = 2
在循环内部进行优化,然后从i = 3
开始,并使用i += 2
移动两次。不过,有一种更好的方式,我会去做。继续前进。
j = 1
For i As Integer = 0 To factors.Count - 1
j = j * factors(i)
Next
If j <> c Then
factors.Add(2)
End If
这......将所有因素重新组合在一起以撤消错误的固定修正。完全删除。
factors.Add(factors.Max + 1)
factors.Sort()
这是Add
的内容是什么?此外,修复了错误后,它们已经排序。
Dim count, num1, totfactor As Integer
Dim totfactors As New List(Of Integer)
For Each num As Integer In factors
If num1 <> num Then
totfactor = count
If totfactor <> 0 Then totfactors.Add(totfactor)
totfactor = 0
End If
If num1 <> num Then count = 0
For i As Integer = 0 To c
If num = i Then
count += 1
Exit For
End If
Next
num1 = num
Next
Dim total As Integer = 1
For Each num As Integer In totfactors
total = total * (num + 1)
Next
我只是想跳过尝试理解这一部分。请放心,它非常慢,因为它从0循环到c以确认因子num
是一个小于c的整数......总是如此。要根据其素数因子分数得到一个数的除数,请将一个加上每个素数的计数加起来:
Dim last As Integer = -1
Dim count As Integer = 0
Dim result As Integer = 1
For Each num As Integer In factors
If num = last Then
count += 1
Else
result *= count + 1
last = num
count = 1
End If
Next
Return result * (count + 1)
所有这些都应该从Θ(N²)到O(N)的时间复杂度。您可以从此处获得答案,并注意它不需要Long
。现在,将其折叠到其他循环中,因为您可以计算不同的素因子并同时找到它们:
Function Divisors(c As Integer) As Integer
Dim d As Integer = c
Dim i As Integer = 2
Dim result As Integer = 1
While d >= i
Dim count As Integer = 1
While d Mod i = 0
d \= i
count += 1
End While
result *= count
i += 1
End While
Return result
End Function
最后,在divisors
和Console.WriteLine
中调用Loop Until
,停止加倍检查指定号码所需的时间:
Sub Main()
Dim number As Integer = 153
Dim pos As Integer = 18
Do
number += pos
pos += 1
Loop Until Divisors(number) > 500
Console.WriteLine(number)
End Sub