using System.Diagnostics;
public static void Main()
for (var i = 1; i <= 5; i++)
var sw = Stopwatch.StartNew();
var result = SPOJ_0074_DIVSUM_v3.sigma(i * 100000);
Console.WriteLine("sigma({0}) = {1} {2}ms", i * 100000, result, sw.ElapsedMilliseconds);
var csSw = Stopwatch.StartNew();
var checksum = SPOJ_0074_DIVSUM_v3.checksum(max);
Console.WriteLine("summing sigma(0)..sigma({0}) ... {1} ({2} ms)", max, checksum, csSw.ElapsedMilliseconds);
class SPOJ_0074_DIVSUM_v3
public const int LIMIT = 500000;
static int[] sigma_cache;
static SPOJ_0074_DIVSUM_v3 ()
sigma_cache = new int[LIMIT + 1];
public static ulong checksum(int n)
for (var i = 0; i <= n; i++)
result += (ulong) sigma(i);
public static int sigma (int n)
static void extend_sigma_cache (int new_limit)
Trace.Assert(sigma_cache != null && new_limit < sigma_cache.Length);
Trace.Assert(sigma_limit >= 1);
for (int n = sigma_limit + 1; n <= new_limit; ++n)
if ((k = gpn_value) >= n) break;
sum += sigma_cache[n - k];
if ((k += gpn_index) >= n) break;
sum += sigma_cache[n - k];
++gpn_index; gpn_value += (gpn_delta += 3);
if ((k = gpn_value) >= n) break;
sum -= sigma_cache[n - k];
if ((k += gpn_index) >= n) break;
sum -= sigma_cache[n - k];
++gpn_index; gpn_value += (gpn_delta += 3);
sum += (gpn_index & 1) != 0 ? n : -n;