📄 zz.c
字号:
#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 + -