Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Euler0549_simple.linq
- // 2016-06-01
- #define FORCE_GC
- #if !LINQPAD
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- #endif
- // # benching 'Euler0549_simple' ...
- //
- // S( 10): 39 0,0 ms
- // S( 100): 2012 0,0 ms
- // S( 1000): 136817 0,1 ms
- // S( 10000): 10125843 1,3 ms
- // S( 100000): 793183093 16,1 ms
- // S( 1000000): 64938007616 216,5 ms
- // S( 10000000): 5494373412573 3.538,4 ms
- // S(100000000): #45a57e1327a02a 66.756,3 ms
- //
- // # benching 'Euler0549_lpf_decomp' ...
- //
- // S( 10): 39 0,0 ms
- // S( 100): 2012 0,0 ms
- // S( 1000): 136817 0,0 ms
- // S( 10000): 10125843 0,3 ms
- // S( 100000): 793183093 1,9 ms
- // S( 1000000): 64938007616 19,5 ms
- // S( 10000000): 5494373412573 196,1 ms
- // S(100000000): #45a57e1327a02a 1.990,3 ms
- class Euler0549_simple_linq: Euler0549
- {
- static void Main ()
- {
- bench_and_print(Euler0549_lpf_decomp.s_sum, "Euler0549_lpf_decomp");
- bench_and_print(Euler0549_simple.s_sum, "Euler0549_simple");
- }
- }
- class Euler0549
- {
- public const int EULER_N = 100000000;
- // computes s(p^e) for p prime
- public static int s_for_prime_power (int p, int e)
- {
- int k = 0;
- while (e > p)
- {
- k += p;
- e -= p + 1;
- for (int t = k; (t /= p) % p == 0; )
- --e;
- }
- return (k + Math.Max(0 , e)) * p;
- }
- public delegate long test_func (int n);
- public static void bench_and_print (test_func f, string name, int lo = 10, int powers_of_ten = 8)
- {
- Console.WriteLine("# benching '{0}' ...\n", name);
- f(2*2*3*3); // get it jitted
- for (int n = lo, e = 0; e < powers_of_ten; n *= 10, ++e)
- {
- Console.Write("S({0,9}): ", n);
- #if FORCE_GC
- force_gc();
- #endif
- var t = Stopwatch.StartNew();
- var x = f(n);
- t.Stop();
- Console.WriteLine("{0,18} {1,10:N1} ms",
- n == EULER_N ? spoiler(x) : x.ToString(),
- t.Elapsed.TotalMilliseconds );
- }
- Console.WriteLine();
- }
- // last <decimal digit count> hex digits of the MD5 of the text representation
- public static string spoiler (long n)
- {
- var text = ASCIIEncoding.ASCII.GetBytes(n.ToString());
- var hash = new System.Security.Cryptography.MD5Cng()
- .ComputeHash(text)
- .Select(x => x.ToString("x2")).Aggregate((s,x) => s + x);
- return "#" + hash.Substring(Math.Max(0, hash.Length - text.Length + 1));
- }
- static void force_gc ()
- {
- System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce;
- GC.Collect(9, GCCollectionMode.Forced);
- }
- }
- class Euler0549_lpf_decomp: Euler0549
- {
- public static int[] s;
- public static long s_sum (int limit)
- {
- int small_prime_limit = (int)Math.Sqrt(limit);
- var small_primes = new List<int>();
- int m = 2;
- s = new int[limit + 1];
- for (int half = limit / 2; m <= half; ++m)
- {
- if (s[m] == 0) // prime
- {
- s[m] = m;
- if (m <= small_prime_limit)
- small_primes.Add(m);
- }
- int s_m = s[m], threshold = limit / m;
- foreach (int p in small_primes)
- {
- if (p > threshold) // i.e. if (p * m > limit)
- break;
- if (m % p != 0) // not a factor of m yet
- {
- // p is a new least factor -> s(p) < s(m) -> s(p * m) = s(m)
- s[p * m] = s_m;
- }
- else // p is already a (least) factor of m
- {
- int e = 2, q = m;
- while ((q /= p) % p == 0)
- ++e;
- s[p * m] = Math.Max(s_for_prime_power(p, e), s[q]);
- break;
- }
- }
- }
- for ( ; m <= limit; ++m)
- if (s[m] == 0)
- s[m] = m;
- long sum = 0;
- for (int i = 2; i <= limit; ++i)
- sum += s[i];
- return sum;
- }
- }
- class Euler0549_simple: Euler0549
- {
- public static long s_sum (int n)
- {
- long result = 0;
- for (int i = 2; i <= n; ++i)
- result += s(factorisation(i));
- return result;
- }
- public static int s (List<int> factors, int lo = 0)
- {
- int p = factors[lo], hi = lo;
- while (++hi < factors.Count && factors[hi] == p)
- ;
- int result = s_for_prime_power(p, hi - lo);
- if (hi < factors.Count)
- result = Math.Max(result, s(factors, hi));
- return result;
- }
- static ushort[] g_small_primes = U16.SmallPrimesUpTo(1 << 16, 6542).ToArray();
- static List<int> factorisation (int n)
- {
- var result = new List<int>();
- int sqrt_n = (int)Math.Sqrt(n);
- foreach (var prime in g_small_primes)
- {
- if (prime > sqrt_n)
- break;
- if (n % prime == 0)
- {
- do result.Add(prime); while ((n /= prime) % prime == 0);
- sqrt_n = (int)Math.Sqrt(n);
- }
- }
- if (n != 1 || result.Count == 0)
- result.Add(n);
- return result;
- }
- }
- class U16
- {
- public static List<ushort> SmallPrimesUpTo (int n, int initial_allocation_size = 0)
- {
- var result = new List<ushort>(initial_allocation_size);
- if (n < 2)
- return result;
- result.Add(2); // needs to be pulled out of thin air because of the mod 2 wheel
- if (n < 3)
- return result;
- result.Add(3); // needs to be pulled out of thin air because of the mod 3 decoder
- int sqrt_n_halved = (int)Math.Sqrt(n) >> 1;
- int max_bit = (n - 1) >> 1;
- var odd_composite = new bool[max_bit + 1];
- for (int i = 5 >> 1; i <= sqrt_n_halved; ++i)
- if (!odd_composite[i])
- for (int p = (i << 1) + 1, j = p * p >> 1; j <= max_bit; j += p)
- odd_composite[j] = true;
- for (int i = 5 >> 1, d = 1; i <= max_bit; i += d, d ^= 3)
- if (!odd_composite[i])
- result.Add((ushort)((i << 1) + 1));
- return result;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement