Advertisement
Guest User

primes.c++

a guest
Jan 13th, 2018
963
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.10 KB | None | 0 0
  1. #include <cassert>
  2. #include <cstdio>
  3. #include <cstring>
  4.  
  5. #include <algorithm>
  6. #include <iostream>
  7. #include <string>
  8. #include <vector>
  9.  
  10. using namespace std;
  11.  
  12.  
  13. class Number {
  14.   private:
  15.     int n;
  16.     unsigned *data;
  17.     Number ( int n );
  18.   public:
  19.     Number ( int n, const string &decimal );
  20.     Number ( const Number &number );
  21.     Number& operator = ( const Number &number );
  22.     ~Number ();
  23.  
  24.     explicit operator bool () const;
  25.     bool equals ( unsigned value ) const;
  26.     bool operator == ( const Number &b ) const;
  27.     bool operator != ( const Number &b ) const;
  28.     bool operator <= ( const Number &b ) const;
  29.     bool operator < ( const Number &b ) const;
  30.     bool operator >= ( const Number &b ) const;
  31.     bool operator > ( const Number &b ) const;
  32.  
  33.     int operator % ( int b ) const;
  34.     Number& operator /= ( int b );
  35.  
  36.     Number operator + ( const Number &b ) const;
  37.     Number operator - ( const Number &b ) const;
  38.     Number operator * ( const Number &b ) const;
  39.     Number operator % ( const Number &b ) const;
  40.  
  41.     Number reduce () const;
  42.     Number shift () const;
  43.     Number negate () const;
  44.  
  45.     static Number random ( const Number &limit );
  46.     Number limit () const;
  47.  
  48.     unsigned long long debug_value () const;
  49.     string debug_str () const;
  50.     void debug ( const char *name, bool full = false ) const;
  51. };
  52.  
  53.  
  54. class Modulo {
  55.   private:
  56.     Number n, r, n1;
  57.     Number mm_shift ( const Number &t ) const;
  58.   public:
  59.     Modulo ( const Number &n );
  60.  
  61.     Number one_ () const;
  62.     Number mul_ ( const Number &a_, const Number &b_ ) const;
  63.     Number pow_ ( Number a_, Number b ) const;
  64. };
  65.  
  66.  
  67. static int cnt[10] = {0};
  68.  
  69. const Number one (10, "1");
  70. const Number two (10, "2");
  71.  
  72. Modulo::Modulo ( const Number &_n) : n (_n), r (_n), n1 (_n) {
  73.   r = n.limit () % n;
  74.   n1 = one;
  75.   Number t = n;
  76.   for (int i = 1; i < 319; i++) {
  77.     n1 = (n1 * t).reduce ();
  78.     cnt[1]++;
  79.     t = (t * t).reduce ();
  80.     cnt[1]++;
  81.   }
  82.   n1 = n1.negate ();
  83. }
  84.  
  85. Number Modulo::mm_shift ( const Number &t ) const {
  86.   Number t2 = t.reduce ();
  87.   t2 = (t2 * n1).reduce ();
  88.   cnt[3]++;
  89.   Number tt = t + t2 * n;
  90.   cnt[3]++;
  91.   Number result = tt.shift ();
  92.   if (result >= n) {
  93.     result = result - n;
  94.   }
  95.   return result;
  96. }
  97.  
  98. Number Modulo::one_ () const {
  99.   return r;
  100. }
  101.  
  102. Number Modulo::mul_ ( const Number &a_, const Number &b_ ) const {
  103.   return mm_shift (a_ * b_);
  104. }
  105.  
  106. Number Modulo::pow_ ( Number a_, Number b ) const {
  107.   Number r_ = r;
  108.   for (; b; b /= 2) {
  109.     if (b % 2) {
  110.       cnt[2] += 3;
  111.       r_ = mm_shift (r_ * a_);
  112.     }
  113.     cnt[2] += 3;
  114.     a_ = mm_shift (a_ * a_);
  115.   }
  116.   return r_;
  117. }
  118.  
  119. vector <int> primes_small;
  120.  
  121. bool check_prime ( const Number &p ) {
  122.   if (p < two)
  123.     return false;
  124.   for (auto x : primes_small) {
  125.     if (p % x != 0)
  126.       continue;
  127.     return p.equals (x);
  128.   }
  129.  
  130.   Modulo m (p);
  131.   Number one_ = m.one_ ();
  132.  
  133.   Number u = p - one;
  134.   int k = 0;
  135.   while (u % 2 == 0)
  136.     k++, u /= 2;
  137.  
  138.   for (int step = 0; step < 100; step++) {
  139.     Number x_ = Number::random (p - one - one) + one, y_ (p);
  140.     x_ = m.pow_ (x_, u);
  141.     if (x_ == one_)
  142.       continue;
  143.     for (int i = 0; i < k; i++) {
  144.       y_ = m.mul_ (x_, x_);
  145.       if (y_ == one_ && !(x_ == p - one_))
  146.         return false;
  147.       x_ = y_;
  148.       if (x_ == one_)
  149.         break;
  150.     }
  151.     if (!(x_ == one_))
  152.       return false;
  153.   }
  154.   return true;
  155. }
  156.  
  157. int main () {
  158.   const int PRIMES_LIMIT = 300;
  159.   static int prime_dividor[PRIMES_LIMIT];
  160.   memset (prime_dividor, 0, sizeof (prime_dividor));
  161.   for (int i = 2; i < PRIMES_LIMIT; i++) {
  162.     if (prime_dividor[i] == 0) {
  163.       primes_small.push_back (i);
  164.       prime_dividor[i] = i;
  165.     }
  166.     for (int j = 0; j < (int)primes_small.size () && primes_small[j] <= prime_dividor[i] && i * primes_small[j] < PRIMES_LIMIT; j++)
  167.       prime_dividor[i * primes_small[j]] = primes_small[j];
  168.   }
  169.  
  170.   srand (301703);
  171.   string sa, sb;
  172.   cin >> sa >> sb;
  173.   Number a (10, sa);
  174.   Number b (10, sb);
  175.  
  176.   int ans = 0;
  177.   for (; a <= b; a = a + one) {
  178.     if (check_prime (a)) {
  179.       fprintf (stderr, "[debug] prime: %s\n", a.debug_str ().c_str ());
  180.       ans++;
  181.     }
  182.   }
  183.   cout << ans << endl;
  184.  
  185.   for (int i = 0; i < 10; i++)
  186.     fprintf (stderr, "cnt[i=%d] = %d\n", i, cnt[i]);
  187.  
  188.   return 0;
  189. }
  190.  
  191.  
  192. Number::Number ( int _n ) : n (_n) {
  193.   data = new unsigned[n];
  194.   // memset (data, 0, sizeof (data[0]) * n);
  195. }
  196.  
  197. Number::Number ( int _n, const string &decimal ) : n (_n) {
  198.   data = new unsigned[n];
  199.   memset (data, 0, sizeof (data[0]) * n);
  200.   for (auto digit : decimal) {
  201.     unsigned long long carry = digit - '0';
  202.     for (int i = 0; i < n; i++) {
  203.       carry = carry + (unsigned long long)data[i] * 10;
  204.       data[i] = carry & 0xffffffff;
  205.       carry >>= 32;
  206.     }
  207.     assert (carry == 0);
  208.   }
  209. }
  210.  
  211. Number::Number ( const Number &number ) : n (number.n) {
  212.   data = new unsigned[n];
  213.   memcpy (data, number.data, sizeof (data[0]) * n);
  214. }
  215.  
  216. Number& Number::operator = ( const Number &number ) {
  217.   assert (n == number.n);
  218.   memcpy (data, number.data, sizeof (data[0]) * n);
  219.   return *this;
  220. }
  221.  
  222. Number::~Number () {
  223.   delete[] data;
  224. }
  225.  
  226. Number::operator bool () const {
  227.   for (int i = 0; i < n; i++)
  228.     if (data[i])
  229.       return true;
  230.   return false;
  231. }
  232.  
  233. bool Number::equals ( unsigned value ) const {
  234.   for (int i = 1; i < n; i++)
  235.     if (data[i])
  236.       return false;
  237.   return data[0] == value;
  238. }
  239.  
  240. bool Number::operator == ( const Number &b ) const {
  241.   assert (n == b.n);
  242.   for (int i = n - 1; i >= 0; i--)
  243.     if (data[i] != b.data[i])
  244.       return false;
  245.   return true;
  246. }
  247.  
  248. bool Number::operator <= ( const Number &b ) const {
  249.   assert (n == b.n);
  250.   for (int i = n - 1; i >= 0; i--)
  251.     if (data[i] != b.data[i])
  252.       return data[i] < b.data[i];
  253.   return true;
  254. }
  255.  
  256. bool Number::operator < ( const Number &b ) const {
  257.   assert (n == b.n);
  258.   for (int i = n - 1; i >= 0; i--)
  259.     if (data[i] != b.data[i])
  260.       return data[i] < b.data[i];
  261.   return false;
  262. }
  263.  
  264. bool Number::operator >= ( const Number &b ) const {
  265.   assert (n == b.n);
  266.   for (int i = n - 1; i >= 0; i--)
  267.     if (data[i] != b.data[i])
  268.       return data[i] > b.data[i];
  269.   return true;
  270. }
  271.  
  272. int Number::operator % ( int b ) const {
  273.   unsigned long long result = 0;
  274.   for (int i = n - 1; i >= 0; i--) {
  275.     result = ((result << 32) + data[i]) % b;
  276.   }
  277.   return result;
  278. }
  279.  
  280. Number& Number::operator /= ( int b ) {
  281.   unsigned long long carry = 0;
  282.   for (int i = n - 1; i >= 0; i--) {
  283.     carry = (carry << 32) + data[i];
  284.     data[i] = carry / b;
  285.     carry %= b;
  286.   }
  287.   return *this;
  288. }
  289.  
  290. Number Number::operator + ( const Number &b ) const {
  291.   assert (n == b.n);
  292.   Number result (n);
  293.   unsigned long long carry = 0;
  294.   for (int i = 0; i < n; i++) {
  295.     carry = carry + data[i] + b.data[i];
  296.     result.data[i] = carry & 0xffffffff;
  297.     carry >>= 32;
  298.   }
  299.   assert (carry == 0);
  300.   return result;
  301. }
  302.  
  303. Number Number::operator - ( const Number &b ) const {
  304.   assert (n == b.n);
  305.   Number result (n);
  306.   unsigned long long carry = 0;
  307.   for (int i = 0; i < n; i++) {
  308.     carry = (1ll << 32) + data[i] - b.data[i] - carry;
  309.     result.data[i] = carry & 0xffffffff;
  310.     carry >>= 32;
  311.     carry = !carry;
  312.   }
  313.   assert (carry == 0);
  314.   return result;
  315. }
  316.  
  317. Number Number::operator * ( const Number &b ) const {
  318.   cnt[0]++;
  319.   assert (n == b.n);
  320.   static long long tmp[200];
  321.   assert (2 * n <= 200);
  322.   memset (tmp, 0, sizeof (tmp[0]) * 2 * n);
  323.   for (int i = 0; i < n; i++)
  324.     for (int j = 0; j < n; j++) {
  325.       unsigned long long t = (unsigned long long)data[i] * b.data[j];
  326.       tmp[i + j] += t & 0xffffffff;
  327.       tmp[i + j + 1] += t >> 32;
  328.     }
  329.  
  330.   Number result (2 * n);
  331.   unsigned long long carry = 0;
  332.   for (int i = 0; i < 2 * n; i++) {
  333.     carry += tmp[i];
  334.     result.data[i] = carry & 0xffffffff;
  335.     carry >>= 32;
  336.   }
  337.   assert (carry == 0);
  338.   return result;
  339. }
  340.  
  341. Number Number::operator % ( const Number &b ) const {
  342.   assert (n >= b.n);
  343.   Number tmp = (*this);
  344.  
  345.   int ib = b.n, it = tmp.n;
  346.   while (ib > 0 && b.data[ib - 1] == 0)
  347.     ib--;
  348.   assert (ib);
  349.  
  350.   while (true) {
  351.     while (it > 0 && tmp.data[it - 1] == 0)
  352.       it--;
  353.     if (it < ib)
  354.       break;
  355.     bool less = false;
  356.     for (int i = 0; i < ib; i++) {
  357.       if (tmp.data[it - i - 1] != b.data[ib - i - 1]) {
  358.         less = tmp.data[it - i - 1] < b.data[ib - i - 1];
  359.         break;
  360.       }
  361.     }
  362.     if (it == ib && less)
  363.       break;
  364.  
  365.     unsigned long long k = tmp.data[it - 1] / b.data[ib - 1];
  366.     int shift = 0;
  367.     if ((k == 1 && less) || k == 0) {
  368.       k = ((unsigned long long)tmp.data[it - 1] << 32) + tmp.data[it - 2];
  369.       k /= b.data[ib - 1];
  370.       shift = 1;
  371.     }
  372.     if (k > 1)
  373.       k /= 2;
  374.  
  375.     assert (k != 0);
  376.  
  377.     unsigned long long carry = 0;
  378.     for (int i = 0; i < ib; i++) {
  379.       int j = i + it - shift - ib;
  380.       unsigned long long value = tmp.data[j] - k * b.data[i] - carry;
  381.       tmp.data[j] = value;
  382.       carry = (tmp.data[j] - value) >> 32;
  383.     }
  384.     if (shift) {
  385.       assert (tmp.data[it - 1] >= carry);
  386.       tmp.data[it - 1] -= carry;
  387.     }
  388.   }
  389.  
  390.   Number result (b.n);
  391.   memcpy (result.data, tmp.data, sizeof (result.data[0]) * b.n);
  392.   return result;
  393. }
  394.  
  395. Number Number::reduce () const {
  396.   Number result (n / 2);
  397.   for (int i = 0; i < n / 2; i++)
  398.     result.data[i] = data[i];
  399.   return result;
  400. }
  401.  
  402. Number Number::shift () const {
  403.   Number result (n / 2);
  404.   for (int i = 0; i < n / 2; i++)
  405.     result.data[i] = data[i + n / 2];
  406.   return result;
  407. }
  408.  
  409. Number Number::negate () const {
  410.   if (!*this)
  411.     return *this;
  412.   Number result (n);
  413.   for (int i = 0; i < n; i++) {
  414.     result.data[i] = 0xffffffff - data[i];
  415.   }
  416.   return result + one;
  417. }
  418.  
  419. Number Number::random ( const Number &limit ) {
  420.   Number result (limit.n);
  421.   bool less = false;
  422.   for (int i = limit.n - 1; i >= 0; i--) {
  423.     result.data[i] = rand () ^ (rand () << 16);
  424.     if (less)
  425.       continue;
  426.     if (limit.data[i] < 0xffffffff)
  427.     result.data[i] %= (limit.data[i] + 1);
  428.     if (result.data[i] < limit.data[i])
  429.       less = true;
  430.   }
  431.   return result;
  432. }
  433.  
  434. Number Number::limit () const {
  435.   Number result (n * 2);
  436.   memset (result.data, 0, sizeof (result.data[0]) * 2 * n);
  437.   result.data[n] = 1;
  438.   return result;
  439. }
  440.  
  441. unsigned long long Number::debug_value () const {
  442.   unsigned long long value = 0;
  443.   for (int i = n - 1; i >= 0; i--)
  444.     value = (value << 32) + data[i];
  445.   return value;
  446. }
  447.  
  448. string Number::debug_str () const {
  449.   string number = "";
  450.   Number tmp = *this;
  451.   while (tmp) {
  452.     number += '0' + (tmp % 10);
  453.     tmp /= 10;
  454.   }
  455.   reverse (number.begin (), number.end ());
  456.   return number;
  457. }
  458.  
  459. void Number::debug ( const char *name, bool full ) const {
  460.   unsigned long long value = 0;
  461.   for (int i = n - 1; i >= 0; i--)
  462.     value = (value << 32) + data[i];
  463.   string number = "";
  464.   Number tmp = *this;
  465.   while (tmp) {
  466.     number += '0' + (tmp % 10);
  467.     tmp /= 10;
  468.   }
  469.   reverse (number.begin (), number.end ());
  470.   fprintf (stderr, "[debug] %s = %s\n", name, number.c_str ());
  471.   if (full) {
  472.     for (int i = n - 1; i >= 0; i--)
  473.       fprintf (stderr, "    [data %d] = 0x%08x\n", i, data[i]);
  474.   }
  475. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement