Advertisement
DarthGizka

Euler0549_simple.linq

Jun 1st, 2016
388
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.74 KB | None | 0 0
  1. // Euler0549_simple.linq
  2. // 2016-06-01
  3.  
  4. #define FORCE_GC
  5.  
  6. #if !LINQPAD
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Diagnostics;
  10. using System.Linq;
  11. using System.Text;
  12. #endif
  13.  
  14. //  # benching 'Euler0549_simple' ...
  15. // 
  16. //  S(       10):                 39        0,0 ms
  17. //  S(      100):               2012        0,0 ms
  18. //  S(     1000):             136817        0,1 ms
  19. //  S(    10000):           10125843        1,3 ms
  20. //  S(   100000):          793183093       16,1 ms
  21. //  S(  1000000):        64938007616      216,5 ms
  22. //  S( 10000000):      5494373412573    3.538,4 ms
  23. //  S(100000000):    #45a57e1327a02a   66.756,3 ms
  24. // 
  25. //  # benching 'Euler0549_lpf_decomp' ...
  26. // 
  27. //  S(       10):                 39        0,0 ms
  28. //  S(      100):               2012        0,0 ms
  29. //  S(     1000):             136817        0,0 ms
  30. //  S(    10000):           10125843        0,3 ms
  31. //  S(   100000):          793183093        1,9 ms
  32. //  S(  1000000):        64938007616       19,5 ms
  33. //  S( 10000000):      5494373412573      196,1 ms
  34. //  S(100000000):    #45a57e1327a02a    1.990,3 ms
  35.  
  36. class Euler0549_simple_linq: Euler0549
  37. {
  38.     static void Main ()
  39.     {
  40.         bench_and_print(Euler0549_lpf_decomp.s_sum, "Euler0549_lpf_decomp");
  41.         bench_and_print(Euler0549_simple.s_sum, "Euler0549_simple");
  42.     }
  43. }
  44.  
  45. class Euler0549
  46. {
  47.     public const int EULER_N = 100000000;
  48.  
  49.     // computes s(p^e) for p prime
  50.     public static int s_for_prime_power (int p, int e)
  51.     {
  52.         int k = 0;
  53.        
  54.         while (e > p)
  55.         {
  56.             k += p;
  57.             e -= p + 1;
  58.    
  59.             for (int t = k; (t /= p) % p == 0; )
  60.                 --e;
  61.         }
  62.    
  63.         return (k + Math.Max(0 , e)) * p;
  64.     }
  65.  
  66.     public delegate long test_func (int n);
  67.  
  68.     public static void bench_and_print (test_func f, string name, int lo = 10, int powers_of_ten = 8)
  69.     {
  70.         Console.WriteLine("# benching '{0}' ...\n", name);
  71.  
  72.         f(2*2*3*3);  // get it jitted
  73.  
  74.         for (int n = lo, e = 0; e < powers_of_ten; n *= 10, ++e)
  75.         {
  76.             Console.Write("S({0,9}): ", n);
  77.  
  78. #if FORCE_GC
  79.             force_gc();
  80. #endif         
  81.             var t = Stopwatch.StartNew();
  82.             var x = f(n);
  83.             t.Stop();
  84.        
  85.             Console.WriteLine("{0,18} {1,10:N1} ms",
  86.                 n == EULER_N ? spoiler(x) : x.ToString(),
  87.                 t.Elapsed.TotalMilliseconds  );
  88.         }
  89.    
  90.         Console.WriteLine();
  91.     }
  92.    
  93.     // last <decimal digit count> hex digits of the MD5 of the text representation
  94.     public static string spoiler (long n)
  95.     {
  96.         var text = ASCIIEncoding.ASCII.GetBytes(n.ToString());
  97.         var hash = new System.Security.Cryptography.MD5Cng()
  98.             .ComputeHash(text)
  99.             .Select(x => x.ToString("x2")).Aggregate((s,x) => s + x);
  100.         return "#" + hash.Substring(Math.Max(0, hash.Length - text.Length + 1));
  101.     }
  102.  
  103.     static void force_gc ()
  104.     {
  105.         System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce;
  106.         GC.Collect(9, GCCollectionMode.Forced);
  107.     }
  108. }
  109.  
  110. class Euler0549_lpf_decomp: Euler0549
  111. {
  112.     public static int[] s;
  113.  
  114.     public static long s_sum (int limit)
  115.     {
  116.         int small_prime_limit = (int)Math.Sqrt(limit);
  117.         var small_primes = new List<int>();
  118.         int m = 2;
  119.  
  120.         s = new int[limit + 1];
  121.  
  122.         for (int half = limit / 2; m <= half; ++m)
  123.         {
  124.             if (s[m] == 0)  // prime
  125.             {
  126.                 s[m] = m;
  127.  
  128.                 if (m <= small_prime_limit)
  129.                     small_primes.Add(m);
  130.             }
  131.  
  132.             int s_m = s[m], threshold = limit / m;
  133.  
  134.             foreach (int p in small_primes)
  135.             {
  136.                 if (p > threshold)  // i.e. if (p * m > limit)
  137.                     break;
  138.  
  139.                 if (m % p != 0)  // not a factor of m yet
  140.                 {
  141.                     // p is a new least factor -> s(p) < s(m) -> s(p * m) = s(m)
  142.                     s[p * m] = s_m;            
  143.                 }
  144.                 else // p is already a (least) factor of m
  145.                 {
  146.                     int e = 2, q = m;
  147.  
  148.                     while ((q /= p) % p == 0)
  149.                         ++e;
  150.  
  151.                     s[p * m] = Math.Max(s_for_prime_power(p, e), s[q]);
  152.                     break;
  153.                 }
  154.             }
  155.         }
  156.  
  157.         for ( ; m <= limit; ++m)
  158.             if (s[m] == 0)
  159.                 s[m] = m;
  160.  
  161.         long sum = 0;
  162.         for (int i = 2; i <= limit; ++i)
  163.             sum += s[i];
  164.  
  165.         return sum;
  166.     }
  167. }
  168.  
  169. class Euler0549_simple: Euler0549
  170. {
  171.     public static long s_sum (int n)
  172.     {
  173.         long result = 0;
  174.    
  175.         for (int i = 2; i <= n; ++i)
  176.             result += s(factorisation(i));
  177.  
  178.         return result;
  179.     }
  180.  
  181.     public static int s (List<int> factors, int lo = 0)
  182.     {
  183.         int p = factors[lo], hi = lo;
  184.    
  185.         while (++hi < factors.Count && factors[hi] == p)
  186.             ;
  187.    
  188.         int result = s_for_prime_power(p, hi - lo);
  189.    
  190.         if (hi < factors.Count)
  191.             result = Math.Max(result, s(factors, hi));
  192.    
  193.         return result;
  194.     }
  195.  
  196.     static ushort[] g_small_primes = U16.SmallPrimesUpTo(1 << 16, 6542).ToArray();
  197.    
  198.     static List<int> factorisation (int n)
  199.     {
  200.         var result = new List<int>();
  201.         int sqrt_n = (int)Math.Sqrt(n);
  202.    
  203.         foreach (var prime in g_small_primes)
  204.         {
  205.             if (prime > sqrt_n)
  206.                 break;
  207.    
  208.             if (n % prime == 0)
  209.             {
  210.                 do result.Add(prime); while ((n /= prime) % prime == 0);
  211.    
  212.                 sqrt_n = (int)Math.Sqrt(n);
  213.             }
  214.         }
  215.        
  216.         if (n != 1 || result.Count == 0)
  217.             result.Add(n);
  218.    
  219.         return result;
  220.     }
  221. }
  222.  
  223.  
  224. class U16
  225. {
  226.     public static List<ushort> SmallPrimesUpTo (int n, int initial_allocation_size = 0)
  227.     {
  228.         var result = new List<ushort>(initial_allocation_size);
  229.    
  230.         if (n < 2)
  231.             return result;
  232.    
  233.         result.Add(2);  // needs to be pulled out of thin air because of the mod 2 wheel
  234.    
  235.         if (n < 3)
  236.             return result;
  237.    
  238.         result.Add(3);  // needs to be pulled out of thin air because of the mod 3 decoder
  239.    
  240.         int sqrt_n_halved = (int)Math.Sqrt(n) >> 1;
  241.         int max_bit = (n - 1) >> 1;
  242.         var odd_composite = new bool[max_bit + 1];
  243.    
  244.         for (int i = 5 >> 1; i <= sqrt_n_halved; ++i)
  245.             if (!odd_composite[i])
  246.                 for (int p = (i << 1) + 1, j = p * p >> 1; j <= max_bit; j += p)
  247.                     odd_composite[j] = true;
  248.    
  249.         for (int i = 5 >> 1, d = 1; i <= max_bit; i += d, d ^= 3)
  250.             if (!odd_composite[i])
  251.                 result.Add((ushort)((i << 1) + 1));
  252.    
  253.         return result;
  254.     }
  255. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement