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

📄 zzx1.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 3 页
字号:
   ap = a.rep.elts();   xp = x.rep.elts();   for (i = 0; i <= da; i++)       mul(xp[i], ap[i], b);}void diff(ZZX& x, const ZZX& a){   long n = deg(a);   long i;   if (n <= 0) {      clear(x);      return;   }   if (&x != &a)      x.rep.SetLength(n);   for (i = 0; i <= n-1; i++) {      mul(x.rep[i], a.rep[i+1], i+1);   }   if (&x == &a)      x.rep.SetLength(n);   x.normalize();}void HomPseudoDivRem(ZZX& q, ZZX& r, const ZZX& a, const ZZX& b){   if (IsZero(b)) Error("division by zero");   long da = deg(a);   long db = deg(b);   if (da < db) {      r = b;      clear(q);      return;   }   ZZ LC;   LC = LeadCoeff(b);   ZZ LC1;   power(LC1, LC, da-db+1);   long a_bound = NumBits(LC1) + MaxBits(a);   LC1.kill();   long b_bound = MaxBits(b);   zz_pBak bak;   bak.save();   ZZX qq, rr;   ZZ prod, t;   set(prod);   clear(qq);   clear(rr);   long i;   long Qinstable, Rinstable;   Qinstable = 1;   Rinstable = 1;   for (i = 0; ; i++) {      zz_p::FFTInit(i);      long p = zz_p::modulus();      if (divide(LC, p)) continue;      zz_pX A, B, Q, R;      conv(A, a);      conv(B, b);            if (!IsOne(LC)) {         zz_p y;         conv(y, LC);         power(y, y, da-db+1);         mul(A, A, y);      }      if (!Qinstable) {         conv(Q, qq);         mul(R, B, Q);         sub(R, A, R);         if (deg(R) >= db)            Qinstable = 1;         else            Rinstable = CRT(rr, prod, R);      }      if (Qinstable) {         DivRem(Q, R, A, B);         t = prod;         Qinstable = CRT(qq, t, Q);         Rinstable =  CRT(rr, prod, R);      }      if (!Qinstable && !Rinstable) {         // stabilized...check if prod is big enough         long bound1 = b_bound + MaxBits(qq) + NumBits(min(db, da-db)+1);         long bound2 = MaxBits(rr);         long bound = max(bound1, bound2);         if (a_bound > bound)            bound = a_bound;         bound += 4;         if (NumBits(prod) > bound)            break;      }   }   bak.restore();   q = qq;   r = rr;}void HomPseudoDiv(ZZX& q, const ZZX& a, const ZZX& b){   ZZX r;   HomPseudoDivRem(q, r, a, b);}void HomPseudoRem(ZZX& r, const ZZX& a, const ZZX& b){   ZZX q;   HomPseudoDivRem(q, r, a, b);}void PlainPseudoDivRem(ZZX& q, ZZX& r, const ZZX& a, const ZZX& b){   long da, db, dq, i, j, LCIsOne;   const ZZ *bp;   ZZ *qp;   ZZ *xp;   ZZ  s, t;   da = deg(a);   db = deg(b);   if (db < 0) Error("ZZX: division by zero");   if (da < db) {      r = a;      clear(q);      return;   }   ZZX lb;   if (&q == &b) {      lb = b;      bp = lb.rep.elts();   }   else      bp = b.rep.elts();   ZZ LC = bp[db];   LCIsOne = IsOne(LC);   vec_ZZ x;   x = a.rep;   xp = x.elts();   dq = da - db;   q.rep.SetLength(dq+1);   qp = q.rep.elts();   if (!LCIsOne) {      t = LC;      for (i = dq-1; i >= 0; i--) {         mul(xp[i], xp[i], t);         if (i > 0) mul(t, t, LC);      }   }   for (i = dq; i >= 0; i--) {      t = xp[i+db];      qp[i] = t;      for (j = db-1; j >= 0; j--) {	 mul(s, t, bp[j]);         if (!LCIsOne) mul(xp[i+j], xp[i+j], LC);	 sub(xp[i+j], xp[i+j], s);      }   }   if (!LCIsOne) {      t = LC;      for (i = 1; i <= dq; i++) {         mul(qp[i], qp[i], t);         if (i < dq) mul(t, t, LC);      }   }         r.rep.SetLength(db);   for (i = 0; i < db; i++)      r.rep[i] = xp[i];   r.normalize();}void PlainPseudoDiv(ZZX& q, const ZZX& a, const ZZX& b){   ZZX r;   PlainPseudoDivRem(q, r, a, b);}void PlainPseudoRem(ZZX& r, const ZZX& a, const ZZX& b){   ZZX q;   PlainPseudoDivRem(q, r, a, b);}void div(ZZX& q, const ZZX& a, long b){   if (b == 0) Error("div: division by zero");   if (!divide(q, a, b)) Error("DivRem: quotient undefined over ZZ");}void div(ZZX& q, const ZZX& a, const ZZ& b){   if (b == 0) Error("div: division by zero");   if (!divide(q, a, b)) Error("DivRem: quotient undefined over ZZ");}staticvoid ConstDivRem(ZZX& q, ZZX& r, const ZZX& a, const ZZ& b){   if (b == 0) Error("DivRem: division by zero");   if (!divide(q, a, b)) Error("DivRem: quotient undefined over ZZ");   r = 0;}staticvoid ConstRem(ZZX& r, const ZZX& a, const ZZ& b){   if (b == 0) Error("rem: division by zero");   r = 0;}void DivRem(ZZX& q, ZZX& r, const ZZX& a, const ZZX& b){   long da = deg(a);   long db = deg(b);   if (db < 0) Error("DivRem: division by zero");   if (da < db) {      r = a;      q = 0;   }   else if (db == 0) {      ConstDivRem(q, r, a, ConstTerm(b));   }   else if (IsOne(LeadCoeff(b))) {      PseudoDivRem(q, r, a, b);   }   else if (LeadCoeff(b) == -1) {      ZZX b1;      negate(b1, b);      PseudoDivRem(q, r, a, b1);      negate(q, q);   }   else if (divide(q, a, b)) {      r = 0;   }   else {      ZZX q1, r1;      ZZ m;      PseudoDivRem(q1, r1, a, b);      power(m, LeadCoeff(b), da-db+1);      if (!divide(q, q1, m)) Error("DivRem: quotient not defined over ZZ");      if (!divide(r, r1, m)) Error("DivRem: remainder not defined over ZZ");   }}void div(ZZX& q, const ZZX& a, const ZZX& b){   long da = deg(a);   long db = deg(b);   if (db < 0) Error("div: division by zero");   if (da < db) {      q = 0;   }   else if (db == 0) {      div(q, a, ConstTerm(b));   }   else if (IsOne(LeadCoeff(b))) {      PseudoDiv(q, a, b);   }   else if (LeadCoeff(b) == -1) {      ZZX b1;      negate(b1, b);      PseudoDiv(q, a, b1);      negate(q, q);   }   else if (divide(q, a, b)) {      // nothing to do         }   else {      ZZX q1;      ZZ m;      PseudoDiv(q1, a, b);      power(m, LeadCoeff(b), da-db+1);      if (!divide(q, q1, m)) Error("div: quotient not defined over ZZ");   }}void rem(ZZX& r, const ZZX& a, const ZZX& b){   long da = deg(a);   long db = deg(b);   if (db < 0) Error("rem: division by zero");   if (da < db) {      r = a;   }   else if (db == 0) {      ConstRem(r, a, ConstTerm(b));   }   else if (IsOne(LeadCoeff(b))) {      PseudoRem(r, a, b);   }   else if (LeadCoeff(b) == -1) {      ZZX b1;      negate(b1, b);      PseudoRem(r, a, b1);   }   else if (divide(a, b)) {      r = 0;   }   else {      ZZX r1;      ZZ m;      PseudoRem(r1, a, b);      power(m, LeadCoeff(b), da-db+1);      if (!divide(r, r1, m)) Error("rem: remainder not defined over ZZ");   }}long HomDivide(ZZX& q, const ZZX& a, const ZZX& b){   if (IsZero(b)) {      if (IsZero(a)) {         clear(q);         return 1;      }      else         return 0;   }   if (IsZero(a)) {      clear(q);      return 1;   }   if (deg(b) == 0) {      return divide(q, a, ConstTerm(b));   }   if (deg(a) < deg(b)) return 0;   ZZ ca, cb, cq;   content(ca, a);   content(cb, b);   if (!divide(cq, ca, cb)) return 0;   ZZX aa, bb;   divide(aa, a, ca);   divide(bb, b, cb);   if (!divide(LeadCoeff(aa), LeadCoeff(bb)))      return 0;   if (!divide(ConstTerm(aa), ConstTerm(bb)))      return 0;   zz_pBak bak;   bak.save();   ZZX qq;   ZZ prod;   set(prod);   clear(qq);   long res = 1;   long Qinstable = 1;   long a_bound = MaxBits(aa);   long b_bound = MaxBits(bb);   long i;   for (i = 0; ; i++) {      zz_p::FFTInit(i);      long p = zz_p::modulus();      if (divide(LeadCoeff(bb), p)) continue;      zz_pX A, B, Q, R;      conv(A, aa);      conv(B, bb);      if (!Qinstable) {         conv(Q, qq);         mul(R, B, Q);         sub(R, A, R);         if (deg(R) >= deg(B))            Qinstable = 1;         else if (!IsZero(R)) {            res = 0;            break;         }         else            mul(prod, prod, p);      }      if (Qinstable) {         if (!divide(Q, A, B)) {            res = 0;            break;         }         Qinstable = CRT(qq, prod, Q);      }      if (!Qinstable) {         // stabilized...check if prod is big enough         long bound = b_bound + MaxBits(qq) +                      NumBits(min(deg(bb), deg(qq)) + 1);         if (a_bound > bound)            bound = a_bound;         bound += 3;         if (NumBits(prod) > bound)             break;      }   }   bak.restore();   if (res) mul(q, qq, cq);   return res;}long HomDivide(const ZZX& a, const ZZX& b){   if (deg(b) == 0) {      return divide(a, ConstTerm(b));   }   else {      ZZX q;      return HomDivide(q, a, b);   }}long PlainDivide(ZZX& qq, const ZZX& aa, const ZZX& bb){   if (IsZero(bb)) {      if (IsZero(aa)) {         clear(qq);         return 1;      }      else         return 0;   }   if (deg(bb) == 0) {      return divide(qq, aa, ConstTerm(bb));   }   long da, db, dq, i, j, LCIsOne;   const ZZ *bp;   ZZ *qp;   ZZ *xp;   ZZ  s, t;   da = deg(aa);   db = deg(bb);   if (da < db) {      return 0;   }   ZZ ca, cb, cq;   content(ca, aa);   content(cb, bb);   if (!divide(cq, ca, cb)) {      return 0;   }    ZZX a, b, q;   divide(a, aa, ca);   divide(b, bb, cb);   if (!divide(LeadCoeff(a), LeadCoeff(b)))      return 0;   if (!divide(ConstTerm(a), ConstTerm(b)))      return 0;   long coeff_bnd = MaxBits(a) + (NumBits(da+1)+1)/2 + (da-db);   bp = b.rep.elts();   ZZ LC;   LC = bp[db];   LCIsOne = IsOne(LC);   xp = a.rep.elts();   dq = da - db;   q.rep.SetLength(dq+1);   qp = q.rep.elts();   for (i = dq; i >= 0; i--) {      if (!LCIsOne) {         if (!divide(t, xp[i+db], LC))            return 0;      }      else         t = xp[i+db];      if (NumBits(t) > coeff_bnd) return 0;      qp[i] = t;      for (j = db-1; j >= 0; j--) {	 mul(s, t, bp[j]);	 sub(xp[i+j], xp[i+j], s);      }   }   for (i = 0; i < db; i++)      if (!IsZero(xp[i]))         return 0;   mul(qq, q, cq);   return 1;}long PlainDivide(const ZZX& a, const ZZX& b){   if (deg(b) == 0)       return divide(a, ConstTerm(b));   else {      ZZX q;      return PlainDivide(q, a, b);   }}long divide(ZZX& q, const ZZX& a, const ZZX& b){   long da = deg(a);   long db = deg(b);   if (db <= 8 || da-db <= 8)      return PlainDivide(q, a, b);   else      return HomDivide(q, a, b);}long divide(const ZZX& a, const ZZX& b){   long da = deg(a);   long db = deg(b);   if (db <= 8 || da-db <= 8)      return PlainDivide(a, b);   else      return HomDivide(a, b);}long divide(ZZX& q, const ZZX& a, const ZZ& b){   if (IsZero(b)) {      if (IsZero(a)) {         clear(q);         return 1;      }      else         return 0;   }   if (IsOne(b)) {      q = a;      return 1;   }   if (b == -1) {      negate(q, a);      return 1;   }   long n = a.rep.length();   vec_ZZ res(INIT_SIZE, n);   long i;   for (i = 0; i < n; i++) {      if (!divide(res[i], a.rep[i], b))         return 0;   }   q.rep = res;   return 1;}long divide(const ZZX& a, const ZZ& b){   if (IsZero(b)) return IsZero(a);   if (IsOne(b) || b == -1) {      return 1;   }   long n = a.rep.length();   long i;   for (i = 0; i < n; i++) {      if (!divide(a.rep[i], b))         return 0;   }   return 1;}long divide(ZZX& q, const ZZX& a, long b){   if (b == 0) {      if (IsZero(a)) {         clear(q);         return 1;      }      else         return 0;   }   if (b == 1) {      q = a;      return 1;   }   if (b == -1) {      negate(q, a);      return 1;   }   long n = a.rep.length();   vec_ZZ res(INIT_SIZE, n);   long i;   for (i = 0; i < n; i++) {      if (!divide(res[i], a.rep[i], b))         return 0;   }   q.rep = res;   return 1;}long divide(const ZZX& a, long b){   if (b == 0) return IsZero(a);   if (b == 1 || b == -1) {      return 1;   }   long n = a.rep.length();   long i;   for (i = 0; i < n; i++) {      if (!divide(a.rep[i], b))         return 0;   }   return 1;}   void content(ZZ& d, const ZZX& f){   ZZ res;   long i;   clear(res);   for (i = 0; i <= deg(f); i++) {      GCD(res, res, f.rep[i]);      if (IsOne(res)) break;   }   if (sign(LeadCoeff(f)) < 0) negate(res, res);   d = res;}void PrimitivePart(ZZX& pp, const ZZX& f){   if (IsZero(f)) {      clear(pp);      return;   }    ZZ d;   content(d, f);   divide(pp, f, d);}staticvoid BalCopy(ZZX& g, const zz_pX& G){   long p = zz_p::modulus();   long p2 = p >> 1;   long n = G.rep.length();   long i;   long t;   g.rep.SetLength(n);   for (i = 0; i < n; i++) {      t = rep(G.rep[i]);      if (t > p2) t = t - p;      conv(g.rep[i], t);   }}   void GCD(ZZX& d, const ZZX& a, const ZZX& b){   if (IsZero(a)) {      d = b;      if (sign(LeadCoeff(d)) < 0) negate(d, d);      return;   }   if (IsZero(b)) {      d = a;      if (sign(LeadCoeff(d)) < 0) negate(d, d);      return;   }   ZZ c1, c2, c;   ZZX f1, f2;   content(c1, a);   divide(f1, a, c1);   content(c2, b);   divide(f2, b, c2);   GCD(c, c1, c2);   ZZ ld;   GCD(ld, LeadCoeff(f1), LeadCoeff(f2));   ZZX g, h, res;

⌨️ 快捷键说明

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