Advertisement
JoelSjogren

roll.cpp (ver9)

Sep 7th, 2016
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.63 KB | None | 0 0
  1. /*
  2.   This is a port of the roll.py Python 3 library to C++.
  3.  
  4.   It works as long as the individual numbers of the input are less than 2^32.
  5.  
  6.   The main function computes the divisors less than 10^8 of 10 tri 10 + 23.
  7.  
  8.   See roll.py for more documentation.
  9. */
  10.  
  11. #include <cstdint>
  12. #include <vector>
  13. #include <map>
  14. #include <iostream>
  15.  
  16. using namespace std;
  17.  
  18. typedef uint64_t nat;
  19.  
  20. struct roll {
  21.   nat flat;
  22.   nat loop;
  23. };
  24.  
  25. nat operator%(nat a, roll b) {
  26.   return a < b.flat ? a : (a - b.flat) % b.loop + b.flat;
  27. }
  28.  
  29. struct divisor_cache {
  30.   vector<nat> primes;
  31.   vector<nat> phi;
  32. };
  33.  
  34. divisor_cache make_cache(nat n) {
  35.   vector<bool> old(n);  // sieve of eratosthenes
  36.   vector<nat> primes;
  37.   vector<nat> phi(n, 1);
  38.   phi[0] = 0;
  39.   for (size_t i = 2; i < n; i++) {
  40.     if (not old[i]) {
  41.       primes.push_back(i);
  42.       for (size_t j = i; j < n; j += i) {
  43.         old[j] = true;
  44.         phi[j] *= i-1;
  45.       }
  46.       for (nat k = i*i; k < n; k *= i) {
  47.         for (size_t j = k; j < n; j += k) {
  48.           phi[j] *= i;
  49.         }
  50.       }
  51.     }
  52.   }
  53.   return {primes, phi};
  54. }
  55.  
  56. nat pow_mod(nat a, nat b, roll c) {
  57.   nat d = 1;
  58.   while (b) {
  59.     if (b % 2) d = d * a % c;
  60.     a = a * a % c;
  61.     b /= 2;
  62.   }
  63.   return d;
  64. }
  65.  
  66. nat gcd(nat a, nat b) {
  67.   if (a == 0 and b == 0) {
  68.     return 0;
  69.   }
  70.   while (b) {
  71.     nat c = a % b;
  72.     a = b;
  73.     b = c;
  74.   }
  75.   return a;
  76. }
  77.  
  78. roll roll_of_powers(nat a, roll b, const divisor_cache& cache) {
  79.   if (a == 0) return {1, 1};
  80.   if (a == 1) return {0, 1};
  81.   nat flat = 0;
  82.   nat a_pow_flat = 1;
  83.   while (a_pow_flat < b.flat) {
  84.     flat++;
  85.     a_pow_flat *= a;
  86.   }
  87.   nat d = b.loop / gcd(b.loop, a_pow_flat);
  88.   nat c = gcd(d, a);
  89.   while (c != 1) {
  90.     d /= c;
  91.     c = gcd(d, c);
  92.     flat++;
  93.   }
  94.   return {flat, cache.phi[d]};
  95. }
  96.  
  97. // (tower of exponents a) % (roll b)
  98. nat mod(const vector<nat>& a, roll b, const divisor_cache& cache) {
  99.   if (a.size() == 0) return 1 % b;
  100.   vector<roll> rolls(a.size());
  101.   rolls[0] = b;
  102.   for (size_t i = 0; i < a.size()-1; i++) {
  103.     rolls[i+1] = roll_of_powers(a[i], rolls[i], cache);
  104.   }
  105.   nat c = 1 % b;
  106.   for (size_t i = a.size()-1; i != (size_t) -1; i--) {
  107.     c = pow_mod(a[i], c, rolls[i]);
  108.   }
  109.   return c;
  110. }
  111.  
  112. void print_divisors(const vector<nat>& tower, nat term, const divisor_cache& cache) {
  113.   for (nat p : cache.primes) {
  114.     if ((mod(tower, {0, p}, cache) + term) % p == 0) {
  115.       cout << p << " " << flush;
  116.     }
  117.   }
  118. }
  119.  
  120. int main(int argc, char ** argv) {
  121.   nat n = 100000000;
  122.   divisor_cache cache = make_cache(n);
  123.   vector<nat> tower(10, 10);
  124.   print_divisors(tower, 23, cache);
  125.   cout << endl;
  126. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement