Project Euler Problem 95
解法
ある数Nの全ての約数はO(√N)で求めることが出来るので,真の約数の和も同じ時間で計算出来る.
よってこれを1000000までの全ての数に行なう.
次にループの確認は今までにアクセスしたものの集合に含まれるものがあるまで,次の数に進み,最終的に元の数に戻っているかで判定出来る.
これはループ回数がそう大きくならないと予想出来るので計算量的には対したことが無いと思われる.
実装(Visual Basic.NET)
この実装だと自分の環境では15.193secで終了する.約数の和を素因数分解を用いて計算すればもう少し早くなる可能性がある.
Imports System Imports System.IO Imports System.Text Imports System.Collections Imports System.Collections.Generic Imports System.Math Imports System.Diagnostics Public Class Algorithm Public Shared Function Divisor(ByVal N As Integer) As Generic.List(Of Integer) Dim M As Integer = Int(Math.Sqrt(N)) Divisor = New Generic.List(Of Integer) For i As Integer = 1 To M If (N Mod i) = 0 Then Divisor.Add(I) If i * i <> N Then Divisor.Add(N / I) End If Next i End Function Public Shared Function Divisor_SUM(ByVal N As Integer) As Integer Divisor_SUM = -N Dim t As Generic.List(Of Integer) = Divisor(N) For Each i As Integer In t Divisor_SUM += i Next End Function End Class Module Module1 Public Answer As String Public Next_Value(1000000) As Integer Public Ac(1000000) As Integer Public Function Solve(ByVal T As Integer) As Integer Solve = 1 Dim V As Integer = T Dim AC As New HashSet(Of Integer) While (1) AC.Add(V) Solve += 1 V = Next_Value(V) If V >= 1000000 Then Return -1 If AC.Contains(V) And V = T Then Exit Function ElseIf AC.Contains(V) Then Return -1 End If End While End Function Sub Main() Dim TimeCounter As New Stopwatch TimeCounter.Start() Answer = "" For i = 0 To 1000000 Next_Value(i) = Algorithm.Divisor_SUM(i) Ac(i) = 0 Next Dim Ans As Integer = 0 Dim AVal As Integer = 0 For i = 0 To 1000000 If Ans < Solve(i) Then Ans = Solve(i) AVal = i Console.WriteLine("Length:{0} Minval:{1}", Ans, AVal) End If Next TimeCounter.Stop() Console.WriteLine("----") Console.WriteLine("Answer:{0}", Answer) Debug.WriteLine("Answer:{0}", Answer) Console.WriteLine("Calculate Time:{0}sec", TimeCounter.ElapsedMilliseconds / 1000) '----- Console.WriteLine() Console.WriteLine("Press Any Key.") Console.ReadKey() End Sub End Module