800 Hybrid Integers.pl 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #!/usr/bin/perl
  2. # Author: Trizen
  3. # Date: 03 November 2022
  4. # https://github.com/trizen
  5. # Hybrid Integers
  6. # https://projecteuler.net/problem=800
  7. # Runtime: 2 seconds.
  8. use 5.020;
  9. use warnings;
  10. use ntheory qw(:all);
  11. use experimental qw(signatures);
  12. sub bsearch_le ($left, $right, $callback) {
  13. my ($mid, $cmp);
  14. for (; ;) {
  15. $mid = int(($left + $right) / 2);
  16. $cmp = $callback->($mid) || return $mid;
  17. if ($cmp < 0) {
  18. $left = $mid + 1;
  19. $left > $right and last;
  20. }
  21. else {
  22. $right = $mid - 1;
  23. if ($left > $right) {
  24. $mid -= 1;
  25. last;
  26. }
  27. }
  28. }
  29. return $mid;
  30. }
  31. sub C ($n, $e) {
  32. my $limit = log($n) * $e;
  33. my $count = 0;
  34. for (my $p = 2 ; ; $p = next_prime($p)) {
  35. my $p_log = log($p);
  36. my $k = bsearch_le($p + 1, int($limit / $p_log), sub ($q) {
  37. $p_log * $q + log($q) * $p <=> $limit;
  38. });
  39. $count += (prime_count($p + 1, $k) || last);
  40. }
  41. return $count;
  42. }
  43. say C(800, 1); #=> 2
  44. say C(163, 165); #=> 1000
  45. say C(800, 800); #=> 10790
  46. say C(800800, 800800);