⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zz.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <NTL/ZZ.h>#include <NTL/vec_ZZ.h>#include <NTL/new.h>NTL_START_IMPLconst ZZ& ZZ::zero(){   static ZZ z;   return z;}const ZZ& ZZ_expo(long e){   static ZZ expo_helper;   conv(expo_helper, e);   return expo_helper;}void AddMod(ZZ& x, const ZZ& a, long b, const ZZ& n){   static ZZ B;   conv(B, b);   AddMod(x, a, B, n);}void SubMod(ZZ& x, const ZZ& a, long b, const ZZ& n){   static ZZ B;   conv(B, b);   SubMod(x, a, B, n);}void SubMod(ZZ& x, long a, const ZZ& b, const ZZ& n){   static ZZ A;   conv(A, a);   SubMod(x, A, b, n);}// ****** input and outputstatic long iodigits = 0;static long ioradix = 0;// iodigits is the greatest integer such that 10^{iodigits} < NTL_WSP_BOUND// ioradix = 10^{iodigits}static void InitZZIO(){   long x;   x = (NTL_WSP_BOUND-1)/10;   iodigits = 0;   ioradix = 1;   while (x) {      x = x / 10;      iodigits++;      ioradix = ioradix * 10;   }   if (iodigits <= 0) Error("problem with I/O");}istream& operator>>(istream& s, ZZ& x){   long c;   long sign;   long ndigits;   long acc;   static ZZ a;   if (!s) Error("bad ZZ input");   if (!iodigits) InitZZIO();   a = 0;   c = s.peek();   while (c == ' ' || c == '\n' || c == '\t') {      s.get();      c = s.peek();   }   if (c == '-') {      sign = -1;      s.get();      c = s.peek();   }   else      sign = 1;   if (c < '0' || c > '9') Error("bad ZZ input");   ndigits = 0;   acc = 0;   while (c >= '0' && c <= '9') {      acc = acc*10 + c - '0';      ndigits++;      if (ndigits == iodigits) {         mul(a, a, ioradix);         add(a, a, acc);         ndigits = 0;         acc = 0;      }      s.get();      c = s.peek();   }   if (ndigits != 0) {      long mpy = 1;      while (ndigits > 0) {         mpy = mpy * 10;         ndigits--;      }      mul(a, a, mpy);      add(a, a, acc);   }   if (sign == -1)      negate(a, a);   x = a;   return s;}struct lstack {   long top;   long alloc;   long *elts;   lstack() { top = -1; alloc = 0; elts = 0; }   ~lstack() { }   long pop() { return elts[top--]; }   long empty() { return (top == -1); }   void push(long x);};void lstack::push(long x){   if (alloc == 0) {      alloc = 100;      elts = (long *) malloc(alloc * sizeof(long));   }   top++;   if (top + 1 > alloc) {      alloc = 2*alloc;      elts = (long *) realloc(elts, alloc * sizeof(long));   }   if (!elts) {      Error("out of space in ZZ output");   }   elts[top] = x;}staticvoid PrintDigits(ostream& s, long d, long justify){   static char *buf = 0;   if (!buf) {      buf = (char *) malloc(iodigits);      if (!buf) Error("out of memory");   }   long i = 0;   while (d) {      buf[i] = (d % 10) + '0';      d = d / 10;      i++;   }   if (justify) {      long j = iodigits - i;      while (j > 0) {         s << "0";         j--;      }   }   while (i > 0) {      i--;      s << buf[i];   }}         ostream& operator<<(ostream& s, const ZZ& a){   static ZZ b;   static lstack S;   long r;   long k;   if (!iodigits) InitZZIO();   b = a;   k = sign(b);   if (k == 0) {      s << "0";      return s;   }   if (k < 0) {      s << "-";      negate(b, b);   }   do {      r = DivRem(b, b, ioradix);      S.push(r);   } while (!IsZero(b));   r = S.pop();   PrintDigits(s, r, 0);   while (!S.empty()) {      r = S.pop();      PrintDigits(s, r, 1);   }         return s;}long GCD(long a, long b){   long u, v, t, x;   if (a < 0)      a = -a;   if (b < 0)      b = -b;   if (a < 0 || b < 0)      Error("GCD: integer overflow");   if (b==0)      x = a;   else {      u = a;      v = b;      do {         t = u % v;         u = v;          v = t;      } while (v != 0);      x = u;   }   return x;}         void XGCD(long& d, long& s, long& t, long a, long b){   long  u, v, u0, v0, u1, v1, u2, v2, q, r;   long aneg = 0, bneg = 0;   if (a < 0) {      a = -a;      aneg = 1;   }   if (b < 0) {      b = -b;      bneg = 1;   }   if (a < 0 || b < 0)      Error("XGCD: integer overflow");   u1=1; v1=0;   u2=0; v2=1;   u = a; v = b;   while (v != 0) {      q = u / v;      r = u % v;      u = v;      v = r;      u0 = u2;      v0 = v2;      u2 =  u1 - q*u2;      v2 = v1- q*v2;      u1 = u0;      v1 = v0;   }   if (aneg)      u1 = -u1;   if (bneg)      v1 = -v1;   d = u;   s = u1;   t = v1;}   long InvMod(long a, long n){   long d, s, t;   XGCD(d, s, t, a, n);   if (d != 1) Error("InvMod: inverse undefined");   if (s < 0)      return s + n;   else      return s;}long PowerMod(long a, long ee, long n){   long x, y;   unsigned long e;   if (ee < 0)      e = -ee;   else      e = ee;   x = 1;   y = a;   while (e) {      if (e & 1) x = MulMod(x, y, n);      y = MulMod(y, y, n);      e = e >> 1;   }   if (ee < 0) x = InvMod(x, n);   return x;}long ProbPrime(long n, long NumTests){   long m, x, y, z;   long i, j, k;   if (n <= 1) return 0;   if (n == 2) return 1;   if (n % 2 == 0) return 0;   if (n == 3) return 1;   if (n % 3 == 0) return 0;   if (n == 5) return 1;   if (n % 5 == 0) return 0;   if (n == 7) return 1;   if (n % 7 == 0) return 0;   if (n >= NTL_SP_BOUND) {      return ProbPrime(to_ZZ(n), NumTests);   }   m = n - 1;   k = 0;   while((m & 1) == 0) {      m = m >> 1;      k++;   }   // n - 1 == 2^k * m, m odd   for (i = 0; i < NumTests; i++) {      do {         x = RandomBnd(n);      } while (x == 0);      // x == 0 is not a useful candidtae for a witness!      if (x == 0) continue;      z = PowerMod(x, m, n);      if (z == 1) continue;         j = 0;      do {         y = z;         z = MulMod(y, y, n);         j++;      } while (j != k && z != 1);      if (z != 1 || y !=  n-1) return 0;   }   return 1;}long MillerWitness(const ZZ& n, const ZZ& x){   ZZ m, y, z;   long j, k;   if (x == 0) return 0;   add(m, n, -1);   k = MakeOdd(m);   // n - 1 == 2^k * m, m odd   PowerMod(z, x, m, n);   if (z == 1) return 0;   j = 0;   do {      y = z;      SqrMod(z, y, n);      j++;   } while (j != k && z != 1);   if (z != 1) return 1;   add(y, y, 1);   if (y != n) return 1;   return 0;}// ComputePrimeBound computes a reasonable bound for trial// division in the Miller-Rabin test.// It is computed a bit on the "low" side, since being a bit// low doesn't hurt much, but being too high can hurt a lot.staticlong ComputePrimeBound(long bn){   long wn = (bn+NTL_ZZ_NBITS-1)/NTL_ZZ_NBITS;   long fn;   if (wn <= 36)      fn = wn/4 + 1;   else      fn = long(1.67*sqrt(double(wn)));   long prime_bnd;   if (NumBits(bn) + NumBits(fn) > NTL_SP_NBITS)      prime_bnd = NTL_SP_BOUND;   else      prime_bnd = bn*fn;   return prime_bnd;}long ProbPrime(const ZZ& n, long NumTrials){   if (n <= 1) return 0;   if (n.SinglePrecision()) {      return ProbPrime(to_long(n), NumTrials);   }   long prime_bnd = ComputePrimeBound(NumBits(n));   PrimeSeq s;   long p;   p = s.next();   while (p && p < prime_bnd) {      if (rem(n, p) == 0)         return 0;      p = s.next();   }   ZZ W;   W = 2;   // first try W == 2....the exponentiation   // algorithm runs slightly faster in this case   if (MillerWitness(n, W))      return 0;   long i;   for (i = 0; i < NumTrials; i++) {      do {         RandomBnd(W, n);      } while (W == 0);      // W == 0 is not a useful candidate for a witness!      if (MillerWitness(n, W))          return 0;   }   return 1;}void RandomPrime(ZZ& n, long l, long NumTrials){   if (l <= 1)      Error("RandomPrime: l out of range");   if (l == 2) {      if (RandomBnd(2))         n = 3;      else         n = 2;      return;   }   do {      RandomLen(n, l);      if (!IsOdd(n)) add(n, n, 1);   } while (!ProbPrime(n, NumTrials));}void NextPrime(ZZ& n, const ZZ& m, long NumTrials){   ZZ x;   if (m <= 2) {      n = 2;      return;   }   x = m;   while (!ProbPrime(x, NumTrials))      add(x, x, 1);   n = x;}long NextPrime(long m, long NumTrials){   long x;   if (m <= 2)       return 2;   x = m;   while (x < NTL_SP_BOUND && !ProbPrime(x, NumTrials))      x++;   if (x >= NTL_SP_BOUND)      Error("NextPrime: no more primes");   return x;}long NextPowerOfTwo(long m){   long k;    long n;   n = 1;   k = 0;   while (n < m && n >= 0) {      n = n << 1;      k++;   }   if (n < 0) Error("NextPowerOfTwo: overflow");   return k;}long NumBits(long a){   unsigned long aa;   if (a < 0)       aa = - ((unsigned long) a);   else      aa = a;   long k = 0;   while (aa) {      k++;      aa = aa >> 1;   }   return k;}long bit(long a, long k){   unsigned long aa;   if (a < 0)      aa = - ((unsigned long) a);   else      aa = a;   if (k < 0 || k >= NTL_BITS_PER_LONG)       return 0;   else      return long((aa >> k) & 1);}long divide(ZZ& q, const ZZ& a, const ZZ& b){   static ZZ qq, r;   if (IsZero(b)) {      if (IsZero(a)) {         clear(q);         return 1;      }      else         return 0;   }   if (IsOne(b)) {      q = a;      return 1;   }   DivRem(qq, r, a, b);   if (!IsZero(r)) return 0;   q = qq;   return 1;}long divide(const ZZ& a, const ZZ& b){   static ZZ r;   if (IsZero(b)) return IsZero(a);   if (IsOne(b)) return 1;   rem(r, a, b);   return IsZero(r);}long divide(ZZ& q, const ZZ& a, long b){   static ZZ qq;   if (!b) {      if (IsZero(a)) {         clear(q);         return 1;      }      else         return 0;   }   if (b == 1) {      q = a;      return 1;   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -