  #include <windows.h>
 #include <stdlib.h>
 extern UINT *Z;
 extern UINT *F;
 extern UINT *st;
 extern UINT mem(UINT);
 extern UINT text1(UINT*);
 UINT menshabs96(UINT*, UINT*);

 void razvert96(UINT a, UINT *b)

 // a - smeshenie v zone zadach slova, predstavljajushego
 // chislo formata "dlinnoe celoe". b - ukazatel na pervuju
 // jachejku dlja sozdanija standartnogo predstavlenija
 // etogo chisla dlja operacij s nim. Takoe predstavlenie
 // sostoit iz 32-bitnih jacheek. Snachala razmeshaetsja
 // smeshenie poslednego nenulevogo 16-bitnogo fragmenta
 // predstavlenija; zatem - znak chisla (0 libo 1 v
 // starshem bite); zatem - idut slova po 32 bita,
 // sootvetstvujushie 16-bitnim fragmentam chisla.
 // Mladshie fragmenti razmeshajutsja v nachale.

 {UINT c,n,k;
  n = Z[a]-3;
  b[0] = n;
  c = Z[a+3];
  b[1] = (c & 0x80000000);
  b[n-1] = (c & 0x0000FFFF);
  b[n] = ((c & 0x7FFFFFFF) >> 16);
  n -= 2;
  k = a + 5;
  while(n != 1)
   {c = Z[k];
    b[n-1] = (c & 0x0000FFFF);
    b[n] = (c >> 16);
    n -= 2;
    k += 2;
   }
  n = b[0];
  while(b[n] == 0 && n != 2)
   {n--;}
  b[0] = n;
 }

 UINT svertdlin(UINT *a)

  // a - ukazatel na predstavlenie chisla-96 (sm.vishe);
  // vozvrashaet dlinu teksta, kotorij nugno sozdat
  // dlja ego svertki.

 {UINT b,c,n;
  b = a[0];
  if(b & 0x00000001)
   {c = a[b];
    if(c & 0x00008000)
     {n = b + 5;}
    else
     {n = b + 3;}
   }
  else
   {n = b + 4;}
  return n;
 }

 void svert96(UINT *a, UINT b)

 // a - ukazatel na predstavlenie chisla-96 (sm. vishe);
 // b - smeshenie v zone zadach blanka teksta dlja
 // hranenija dlinnogo celogo. Etot blank zapolnjaetsja
 // po a.

 {UINT c,m,n,k;
   n = a[0]; m = n & 0x00000001;
   if(m == 0)
    {c = a[1] | a[n];
     n--;
    }
   else
    {if(a[n] & 0x00008000)
      {c = a[1];
      }
     else
      {c = (a[n] << 16);
       c |= a[1];
       c |= a[n-1];
       n -= 2;
      }
    }
   Z[b+2] = 0x61200001;
   Z[b+3] = c;
   k = b + 4;
   while(n != 1)
    {c = (a[n] << 16);
     c |= a[n-1];
     Z[k] = 0x61200001;
     Z[k+1] = c;
     k += 2;
     n -= 2;
    }
 }

 UINT plus96(UINT *a, UINT *b)

 // a,b - ukazateli na predstavlenija chisel-96. K pervomu
 // chislu pribavljaetsja vtoroe. Vozvrashaet ukazatel
 // perepolnenija: nenulevoe znachenie - est perepolnenie.

 {UINT c,d,e,f,m;
  if(a[1] == b[1])
   {c = b[0]; e = 0;
    m = a[0];
    for(d = 2; d <= c; d++)
     {e += (m < d ? 0 : a[d]);
      e += b[d];
      a[d] = (e & 0x0000FFFF);
      e >>= 16;
     }
    if(m < c)a[0] = c;
    while(e != 0)
     {e += (m < d ? 0 : a[d]);
      a[d] = (e & 0x0000FFFF);
      e >>= 16;
      if(a[0] < d)a[0] = d;
      d++;
     }
    if(a[0] > 252)e = 1;
    return e;
   }
  else
   {if(menshabs96(b,a))
     {c = b[0]; e = 0;
      for(d = 2; d <= c; d++)
       {f = (a[d] | 0x00010000);
        f -= e;
        f -= b[d];
        a[d] = (f & 0x0000FFFF);
        e = 1 - (f >> 16);
       }
      while(e != 0)
       {f = (a[d] | 0x00010000);
        f -= e;
        a[d] = (f & 0x0000FFFF);
        e = 1 - (f >> 16);
        d++;
       }
      for(d = a[0]; 2 <= d; d--)
       {if(a[d] != 0)
         {a[0] = d; return 0;}
       }
      a[0] = 2; a[1] = 0;
      return 0;
     }
    else
     {c = a[0]; e = 0; m = b[0];
      for(d = 2; d <= c; d++)
       {f = (b[d] | 0x00010000);
        f -= e;
        f -= a[d];
        a[d] = (f & 0x0000FFFF);
        e = 1 - (f >> 16);
       }
      while(d <= m)
       {f = (b[d] | 0x00010000);
        f -= e;
        a[d] = (f & 0x0000FFFF);
        e = 1 - (f >> 16);
        a[0] = d;
        d++;
       }
      a[1] = b[1];
      for(d = b[0]; 2 <= d; d--)
       {if(a[d] != 0)
         {a[0] = d; return 0;}
       }
      a[0] = 2; a[1] = 0;
      return 0;
     }
   }
 }

 void minus96(UINT *a)

  // a - ukazatel na predstavlenie chisla-96. U etogo
  // chisla menjaetsja znak.

 {if(a[0] == 2 && a[2] == 0)return;
  else a[1] ^= 0x80000000;
 }

 UINT menshabs96(UINT *a, UINT *b)
  // a,b - ukazateli na predstavlenija chisel-96.
  // Esli abs.velichina pervogo menshe abs. velichini
  // vtorogo, to vozvrashet 1, inache 0


 {UINT c;
  if(a[0] == b[0])
   {for(c = a[0]; 2 <= c; c --)
     {if(a[c] < b[c]) return 1;
      if(b[c] < a[c]) return 0;
     }
    return 0;
   }
  else
   {if(a[0] < b[0]) return 1;
    return 0;
   }
 }

 void umnog10(UINT *a)

 // a - ukazatel na predstavlenie chisla-96. Eto chislo
 //  umnogaetsja na 10. Perepolnenie ignoriruetsja.

 {UINT b,c,d;
  b = a[0]; d = 0;
  for(c = 2; c <= b; c++)
   {d += (a[c]*10);
    a[c] = (d & 0x0000FFFF);
    d >>= 16;
   }
  while(d != 0)
   {a[c] = (d & 0x0000FFFF);
    d >>= 16;
    c++;
   }
  c--;
  a[0] = c;
 }

 void cifrplus96(UINT *a, UINT b)

  // a - ukazatel na predstavlenie neotricatelnogo
  // chisla-96; b - cifra v formate UINT. Proishodit
  // pribavlenie etoj cifri k chislu. Perepolnenie
  // ignoriruetsja.

 {UINT c,d,k;
  d = a[2] + b;
  a[2] = (d & 0x0000FFFF);
  d >>= 16; c = 3;
  k = a[0];
  while(d != 0)
   {d += (k < c ? 0 : a[c]);
    a[c] = (d & 0x0000FFFF);
    d >>= 16;
    if(k < c)
     {a[0] = c;}
    c++;
   }
 }

 UINT delenie10(UINT *a)

 //a - ukazatel na predstavlenie chisla-96. Eto chislo
 //delitsja na 10. Vozvrashaet ostatok.

 {UINT b,c,d;
  ldiv_t e;
  b = a[0];
  c = 0;
  for(d = b; 2 <= d; d--)
   {c |= a[d];
    e = ldiv(c,10);
    a[d] = e.quot;
    c = e.rem;
    if (d != 2)
    c <<= 16;
   }
  if(a[b] == 0 && b != 2)
   a[0] -= 1;
  return c;
 }

 UINT umnog96(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na somnogiteli v formate chisel-96;
 // c - ukazatel na nakopitel rezultata dlja chisla-96.
 // Vozvrashaet indikator perepolnenija (0 - net
 // perepolnenija).

 {UINT i,j,k,m,d,e;
   m = 0;
   c[1] = 0;
   for(i = 2; i <= b[0]; i++)
    {d = 0;
     for(j = 2, k = i; j <= a[0]; j++, k++)
      {e = b[i] * a[j];
       d += (e & 0x0000FFFF);
       if(k <= m)d += c[k];
       c[k] = (d & 0x0000FFFF);
       d >>= 16;
       e >>= 16;
       d += e;
      }
     m = k - 1;
     while(d != 0)
      {if(k <= m)d += c[k];
       c[k] = (d & 0x0000FFFF);
       d >>= 16;
       m = k;
       k++;
      }
    }
   if(a[1] != b[1]) c[1] = 0x80000000;
   for(i = m; 2 <= i; i--)
    {if(c[i] != 0)
      {c[0] = i;
       if(252 < i)return 1;
       return 0;
      }
    }
   c[0] = 2; c[1] = 0;
   return 0;
 }

 void divznak96(UINT *a, UINT *b, UINT *c, UINT *d)

  // a,b - ukazateli na delimoe i delitel;
  // c,d - nepolnoe chastnoe i ostatok delenija
  // modulej a,b; vse eto - v formate chisel-96.
  // Correktiruet rezultati s uchetom znakov a,b.

  {if(a[1] != 0)
    {if(d[0] != 2 || d[2] != 0)
      {if(b[1] == 0)
        {d[1] = 0x80000000;}
       plus96(d,b);
       d[1] = 0;
       cifrplus96(c,1);
      }
     if(b[1] == 0 && (c[2] != 0 || c[0] != 2))
      {c[1] = 0x80000000;}
     return;
    }
   else
    {if(b[1] != 0 && (c[2] != 0 || c[0] != 2))
      {c[1] = 0x80000000;}
     return;
    }
  }

 UINT delenie96(UINT *a, UINT *b, UINT *c, UINT *d)

 // a,b - ukazateli na delimoe i delitel v formate
 // chisel-96; c,d - ukazateli na nakopiteli nepolnogo
 // chastnogo i ostatka v formate chisla-96.
 // Vozvrashaet indikator delenija na 0 (0 - net
 // delenija na 0).

 {UINT e,f,i,j,k,h,p,q,r;
  ldiv_t g;

  if(a[0] == 2 || (a[0] == 3 && a[3] < 0x00008000))
   {e = (a[0] == 2 ? 0 : (a[3] << 16));
    e |= a[2];
    if(b[0] == 2 || (b[0] == 3 && b[3] < 0x00008000))
     {f = (b[0] == 2 ? 0: (b[3] << 16));
      f |= b[2];
      if(f == 0)return 1;
      g = ldiv(e,f);
      c[3] = (g.quot >> 16);
      c[2] = (g.quot & 0x0000FFFF);
      d[3] = (g.rem >> 16);
      d[2] = (g.rem & 0x0000FFFF);
      c[0] = (c[3] == 0 ? 2 : 3);
      d[0] = (d[3] == 0 ? 2 : 3);
      c[1] = 0; d[1] = 0;
      divznak96(a,b,c,d);
      return 0;
     }
    else
     {d[0] = a[0];
      d[2] = a[2];
      d[3] = a[3];
      c[0] = 2;
      c[1] = 0;
      d[1] = 0;
      c[2] = 0;
      divznak96(a,b,c,d);
      return 0;
      }
   }
  else
   {if(b[0] == 2)
     {e = b[2];
      if(e == 0)return 1;
      if(e == 1)
       {for(i = 2; i <= a[0]; i++)
         {c[i] = a[i];}
        c[0] = a[0];
        c[1] = 0;
        d[0] = 2;
        d[1] = 0;
        d[2] = 0;
        divznak96(a,b,c,d);
        return 0;
       }
      i = a[0];
      f = (a[i] << 16);
      for(j = 0; j <= i; j++)
      c[j] = 0;
      for(j = i-1; 2 <= j; j--,i--)
       {f |= a[j];
        if(!(f & 0x80000000))
         {g = ldiv(f,e);
          c[i] += (g.quot >> 16);
          c[j] += (g.quot & 0x0000FFFF);
          f = (g.rem << 16);
         }
        else
         {h = (f & 1);
          f >>= 1;
          g = ldiv(f,e);
          p = (g.quot << 1);
          c[i] += (p >> 16);
          c[j] += (p & 0x0000FFFF);
          p = g.rem;
          p <<= 1;
          h += p;
          g = ldiv(h,e);
          c[i] += (g.quot >> 16);
          c[j] += (g.quot & 0x0000FFFF);
          f= (g.rem << 16);
         }
       }
      d[2] = (f >> 16);
      d[0] = 2;
      d[1] = 0;
      i = a[0];
      while(c[i] == 0)
       {i--;}
      c[0] = i;
      divznak96(a,b,c,d);
      return 0;
     }
    else
     {if(menshabs96(a,b))
       {c[0] = 2;
        for(i = 2; i <= a[0]; i++)
         {d[i] = a[i];}
        d[0] = a[0];
        c[1] = 0;
        d[1] = 0;
        c[2] = 0;
        divznak96(a,b,c,d);
        return 0;
       }
      i = a[0];
      for(j = 0; j <= i+1; j++)
       {c[j] = 0; d[j] = 0;
       }
      c[0] = a[0];
      i =b[0];
      e = b[i];
      r = 0;     // r - velichina sdviga vlevo
      if(!(e & 0x0000FF00))
       {e <<= 8; r += 8;
       }
      if(!(e & 0x0000F000))
       {e <<= 4; r += 4;
       }
      if(!(e & 0x0000C000))
       {e <<= 2; r += 2;
       }
      if(!(e & 0x00008000))
       {e <<= 1; r += 1;
       }
      p = 16 - r; // p - sdvig vpravo predidushih
                  // razrjadov
      if(r != 0)     // sdvig vlevo delimogo i delitelja
       {while(2 < i)
         {h = b[i-1];
          e |= (h >> p);
          b[i] = e;
          e = ((h << r) & 0x0000FFFF);
          i -= 1;
         }
        b[2] = e;
        i = a[0];
        e = (a[i] << r);
        h = (e & 0xFFFF0000);
        if(h != 0)
         {a[i+1] = (h >> 16);
          a[0] += 1;
         }
        e &= 0x0000FFFF;
        while(2 < i)
         {h = a[i-1];
          e |= (h >> p);
          a[i] = e;
          e = ((h << r) & 0x0000FFFF);
          i -= 1;
         }
        a[2] = e;
       }
      i = b[0];
      e = b[i];
      e += 1;
      while(!(menshabs96(a,b)))
       {j = a[0];
        if(e <= a[j] || (j == i))
         {j -= i;
          j += 2;
          f = c[j];
          f += 1;
          c[j] = (f & 0x0000FFFF);
          f >>= 16;
          while(f != 0)
           {j++;
            f += c[j];
            c[j] = (f & 0x0000FFFF);
            f >>= 16;
           }
          k = (a[0] - b[0]) + 2;
          q = 0;              // vichitanie iz "a"
          for(j = 2; j <= b[0]; j++, k++)
           {f = (a[k] | 0x00010000);
            f -= q;
            f -= b[j];
            a[k] = (f & 0x0000FFFF);
            q = 1 - (f >> 16);
           }
          k = a[0];
          a[0] = 2;
          for(j = k; 2 <= j; j--)
           if(a[j] != 0)
            {a[0] = j;break;}
         }
        else
         {f = (a[j] << 16);
          f |= a[j-1];
          h = f/e;     // h - lokalnoe chastnoe
          j -= i;
          j += 1;
          f = c[j];   // korrekcija "c"
          f += h;
          c[j] = (f & 0x0000FFFF);
          f >>= 16;
          while(f != 0)
           {j++;
            f += c[j];
            c[j] = (f & 0x0000FFFF);
            f >>= 16;
           }
          q = 0;
          for(j = 2; j <= i; j++) // domnogenie "b"
           {f = b[j] * h;
            q += (f & 0x0000FFFF);
            d[j] = (q & 0x0000FFFF);
            q >>= 16;
            q += (f >> 16);
           }
          d[j] = q;
          d[0] = j;
          k = (a[0] - j) + 2;
          q = 0;              // vichitanie iz "a"
          for(j = 2; j <= d[0]; j++, k++)
           {f = (a[k] | 0x00010000);
            f -= q;
            f -= d[j];
            a[k] = (f & 0x0000FFFF);
            q = 1 - (f >> 16);
           }
          k = a[0];
          a[0] = 2;
          for(j = k; 2 <= j; j--)
           if(a[j] != 0)
            {a[0] = j;break;}
         }
       }
      for(i = 2; i <= a[0]; i++)
       {d[i] = a[i];}
      if(r != 0)
       {f = 0;
        for(i = a[0]; 2 <= i; i--)
         {e = d[i];
          d[i] = (e >> r) | f;
          f = ((e << p) & 0x0000FFFF);
         }
       }
      d[0] = 2;
      for(j = a[0]; 2 <= j; j--)
       if(d[j] != 0)
        {d[0] = j;break;}
       for(j = c[0]; 2<= j; j--)
       if(c[j] != 0)
        {c[0] = j;break;}
      divznak96(a,b,c,d);
      return 0;
     }
   }
 }

 void plusmod96(UINT *a, UINT *b, UINT *c)
  // a,b,c - ukazateli na predstavlenija slagaemih
  // i modulja. K pervomu chislu pribavljaetsja vtoroe
  // i privoditsja po modulju c.

 {plus96(a,b);
  if(!(menshabs96(a,c)))
   {minus96(c);
    plus96(a,c);
    minus96(c);
   }
 }

 void minusmod96(UINT *a, UINT *b)
  // a,b - ukazateli na predstavlenija chisla i modulja.
  // Chislo zamenjaetsja na b-a.

  {if(a[0] == 2 && a[2] == 0)return;
   minus96(a);
   plus96(a,b);
  }

 void umnogmod96(UINT *a, UINT *b, UINT *c, UINT *d)
  // a,b,c - ukazateli na somnogiteli i na modul;
  // d - ukazatel na nakopitel rezultata.

  {UINT *f,*g,i,*e;
   f = F + 900;
   g = F + 600;
   e = F + 1200;
   umnog96(a,b,g);
   for(i = 0; i <= c[0]; i++)
    e[i] = c[i];
   delenie96(g,e,f,d);
  }

 UINT deleniemod96(UINT *a, UINT *b, UINT *c, UINT *d)
  // a,b,c - ukazateli na delimoe, delitel i modul;
  // d - ukazatel na nakopitel rezultata.
  // Esli delenie nevozmogno, vozvrashaet 1, inache 0.

  {UINT *e,*f,*h,*m,*p,*q,i,k,g,r,*s;
   if(b[0] == 2 && b[2] == 1)
    {for(i = 0; i <= a[0]; i++)
      d[i] = a[i];
     return 0;
    }
   e = F + 300;
   e[0] = 2; e[1] = 0; e[2] = 1;
   f = e + 300;
   h = f + 300;
   m = h + 300;
   p = m + 300;
   q = p + 300;
   s = q + 300;
   for(i = 0; i <= c[0]; i++)
    m[i] = c[i];
   for(i = 0; i <= b[0]; i++)
    p[i] = b[i];
   r = delenie96(m,p,f,h);
   if(r != 0) return 1;
   g = 0;
   for(i = 0; i <= b[0]; i++)
    m[i] = b[i];
   while((h[0] != 2) || (h[2] != 0))
    {for(i = 0; i <= h[0]; i++)
      s[i] = h[i];
     delenie96(m,s,p,q);
     k = h[0];
     for(i = 0; i <= k; i ++)
      {m[i] = h[i]; h[i] = q[i];
      }
     umnog96(p,f,q);
     plus96(q,e);
     for(i = 0; i <= f[0]; i++)
      {e[i] = f[i];
      }
     for(i = 0; i <= c[0]; i++)
      s[i] = c[i];
     delenie96(q,s,p,f);
     g = 1 - g;
    }
   umnog96(e,a,p);
   for(i = 0; i <= c[0]; i++)
    s[i] = c[i];
   delenie96(p,s,q,d);
   if(g == 1)
    {minus96(d);
     plus96(d,c);
    }
   return 0;
  }
 UINT delmod96(UINT a, UINT b, UINT c)
  // a,b,c - delimoe, delitel i modul, prichem modul
  // imeet ne bolee 16 bit. Vozvrashaet chastnoe.

 {UINT d,f,g,i,p;
  ldiv_t h;
  d = 1;
  h = ldiv(c,b);
  f = h.rem;
  g = h.quot;
  i = 0;
  while(f != 0)
   {h = ldiv(b,f);
    p = h.quot;
    p *= g;
    p += d;
    p %= c;
    d = g;
    g = p;
    i = 1 - i;
    b = f;
    f = h.rem;
   }
  p = d * a;
  p %= c;
  if(i == 1)
   p = c - p;
  return p;
 }

 void razvertmn96(UINT a, UINT *b)

 // a - smeshenie v zone zadach nabora, predstavljajushego
 // mnogochlen. b - ukazatel na jachejku, nachinaja s
 // kotoroj nugno sozdat predstavlenie mnogochlena,
 // imejushego koefficienti tipa "dlinnoe celoe".
 // Eto predstavlenie vkljuchaet v sebja:
 //  a) chislo chlenov mnogochlena (32 bita);
 //  b) 256 jacheek, opredeljajushih modul, po
 //     kotoromu rassmatrivaetsja mnogochlen,
 //     libo (dlja mnogochlena nad celimi chislami) 1;
 //  c) idushie podrjad 256-jacheechnie koefficienti
 //     mnogochlena, nachinaja s mladshego.

 {UINT n,c;
  n = Z[a] - 6; n >>= 1; // n - stepen;
  b[0] = n; b++;
  a += 2;
  while(!(Z[a] & 0x80000000))
   {c = Z[a];
    razvert96(c,b);
    b += 256;
    a += 2;
   }
  return;
 }

 UINT svertmn96(UINT *a)

 // a - ukazatel na jachejku, nachinaja s kotoroj
 // zapisan mnogochlen v formate dlinnogo celogo.
 // V zone zadach sozdajetsja zapis etogo mnogochlena.
 // Vozvrashaet ee smeshenie. Pri neudache vozvrashaet
 // 0xFFFFFFFF.

 {UINT b,n,i,k,*c;
  n = *a; c = st; a += 1;
  for(i = 0; i <= n; i++)
   {k = svertdlin(a);
    b= mem(k);
    if(b == 0) return 0xFFFFFFFF;
    svert96(a,b);
    a += 256;
    *st = b;
    st++;
   }
  b = text1(c);
  if(b == 0) return 0xFFFFFFFF;
  return b;
 }

 void normmn96(UINT *a)
 // a - ukazatel na predstavlenie mnogochlena v formate
 // dlinnogo celogo. Utochnjaet chislo ego nenulevih
 // chlenov.

 {UINT b,i;
  i = *a;
  b = i;
  i <<= 8;
  while(a[i+1] == 2 && a[i+3] == 0 && b != 1)
   {i -= 256; b--;}
  *a = b;
 }

 UINT plusmn96(UINT *a, UINT *b)

 //a, b - ukazateli na nachala mnogochlenov. k pervomu
 // iz nih pribavljaetsja vtoroj. Pri perepolnenii
 // vozvrashaet 1, inache - 0. Predpolagaetsja, chto posle
 // mnogochlena a imeetsja dostatochno mesta dlja
 // starshih stepenej summi.

 {UINT c,d,m,n,*e,*f,*g;
  c = *a; d = *b;
  if(c < d)
   {n = c+1; n <<= 8; n++;
    m = d+1; m <<= 8;
    while(n <= m)
     {a[n] = 2; a[n+1] = 0; a[n+2] = 0;
      n += 256;
     }
    *a = d;
   }
  if(a[1] != 2 || a[3] != 1)
   {e = a+1;
    for(n = 1, f = a+257, g = b+257; n <= d; n++,
        f += 256, g += 256)
     {plusmod96(f,g,e);
     }
   }
  else
   {for(n = 1, f = a+257, g = b+257; n <= d; n++,
        f += 256, g += 256)
     {c = plus96(f,g);
      if(c != 0)return 1;
     }
   }
  normmn96(a);
  return 0;
 }

 UINT umnogmn96(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na somnogiteli; c - ukazatel na
 // nachalo massiva dlja rezultata. Etot massiv ne
 // predpolagaetsja kak-libo inicializirovannim.
 // Pri perepolnenii vozvrashaet 1, inache - 0.

 {UINT i,j,k,m,n,p,*d,*e,*f,*g;
  m = a[0] + b[0]; m--;
  c[0] = m;
  for(i = 1; i <= a[1]+1; i++)
   c[i] = a[i];
  n = 257;
  for(j = 1; j <= m; j++)
   {c[n] = 2; c[n+1] = 0; c[n+2] = 0;
    n += 256;
   }
  m = a[0];
  n = b[0];
  k = (a[1] == 2 && a[3] == 1 ? 0 : 1); // indikator mod
  for(i = 1,d = b+257,e = c+257; i<= n; i++,d += 256,
      e += 256)
   {for(j = 1,f = a+257,g = e; j <= m; j++, f += 256,
        g += 256)
     {if(k == 0)
       {p = umnog96(d,f,F);
        if(p != 0)return 1;
        plus96(g,F);
       }
      else
       {umnogmod96(d,f,a+1,F);
        plusmod96(g,F,a+1);
       }
     }
   }
  normmn96(c);
  return 0;
 }

 UINT delmnog96(UINT *a, UINT *b, UINT *c)

 // a,b - ukazateli na delimoe i delitel;
 // c - ukazatel na nachalo massiva dlja nepolnogo
 // chastnogo. Delit s ostatkom a na b, prichem ostatok
 // poluchaetsja v a. Esli delenie nevozmogno,
 // vozvrashaet 1, inache 0.

 {UINT i,j,k,*e,*f,*g,h,p,*q,m;
  i = a[0]; j = b[0];
  m = (i > j ? i-j : 0); m++;
  c[0] = m;
  for(k = 1; k <= a[1]+1; k++)
   c[k] = a[k];
  m <<= 8;
  m += 1;
  c[257] = 2;
  c[258] = 0;
  c[259] = 0;
  i <<= 8;
  j <<= 8;
  i++; j++;
  g = F + 256;
  k = (a[1] == 2 && a[3] == 1 ? 0 : 1); // indikator mod
  while(i >= j)
   {e = a + i;
    f = b + j;
    if(k == 0)
     {h = delenie96(e,f,F,g);
      if(h != 0 || g[0] != 2 || g[2] != 0)return 1;
     }
    else
     {h = deleniemod96(e,f,a+1,F);
      if(h != 0)return 1;
     }
    q = c + m;
    for(p = 0; p <= F[0]; p++)
     {q[p] = F[p];
     }
    m -= 256;
    q = b + 1;
    i -= 256;e -= 256;
    f -= 256;
    while(f != q)
     {if(k == 0)
       {h = umnog96(F,f,g);
        if(h != 0)return 1;
        minus96(g);
        h = plus96(e,g);
        if(h != 0)return 1;
       }
      else
       {umnogmod96(F,f,a+1,g);
        minusmod96(g,a+1);
        plusmod96(e,g,a+1);
       }
      e -= 256;
      f -= 256;
     }
    p = 1; e = a + i; f = a + j;
    while(p == 1 && e >= f)
     {if(e[0] == 2 && e[2] == 0)
       {i -= 256;
        e -= 256;
        q = c + m;
        q[0] = 2; q[1] = 0; q[2] = 0;
        m -= 256;
       }
      else p = 0;
     }
   }
  i--;
  i >>= 8;
  if(i == 0)
   {i = 1;
    a[257] = 2;
    a[258] = 0;
    a[259] = 0;
   }
  a[0] = i;
  normmn96(a);
  return 0;
 }

 UINT domnogmn96(UINT *a,UINT *b)

 // a - ukazatel na mnogochlen; b - ukazatel na chislo.
 // Vse chleni mnogochlena domnogajutsja na eto chislo.
 // Pri nalichii perepolnenija vidaet 1, inache 0.

 {UINT n,i,j,k,p,*f;
  n = a[0];
  k = (a[1] == 2 && a[3] == 1 ? 0 : 1); // indikator mod
  f = a + 257;
  for(i = 1; i <= n; i++)
   {if(k == 0)
     {p = umnog96(f,b,F);
      if(p != 0) return 1;
     }
    else umnogmod96(f,b,a+1,F);
    for(j = 0; j <= F[0]; j++)
    f[j] = F[j];
    f += 256;
   }
  normmn96(a);
  return 0;
 }

 void minusmn96(UINT* a)

 // a - ukazatel na mnogochlen;

 {UINT n,i,k,*b;
  n = a[0];
  k = (a[1] == 2 && a[3] == 1 ? 0 : 1); // indikator mod
  b = a + 257;
  for(i = 1; i <= n; i++)
   {if(k == 0)minus96(b);
    else minusmod96(b,a+1);
    b += 256;
   }
 }

UINT* nod96(UINT* a, UINT* b, UINT* c, UINT* d, UINT* r)

  //a,b - ukazateli na predstavlenija chisel-96;
  //c,d,r - ukazateli na vspomogatelnie massivi dlja
  // treh chisel - 96. Nahodit naibolshij obshij delitel
  // a i b; vozvrashaet ukazatel ne ego predstavlenie.
  // Chisla a,b mogut portitsja.

{UINT i,*e;
 a[1] = 0; b[1] = 0;
 if(menshabs96(b,a) == 1)
  {e = a; a = b; b = e;
  }
 while(a[0] != 2 || a[2] != 0)
  {for(i = 0; i <= a[0]; i++)
    {r[i] = a[i];}
   delenie96(b,a,c,d);
   e = b; b = r; r = e;
   e = a; a = d; d = e;
  }
 return b;
}

UINT ostmn96(UINT* a, UINT* b)

//a,b - ukazateli na mnogochleni. Vipolnjajetsja
// obobshennoe delenie a na b, prichem v a poluchaetsja
// ostatok. Pri perepolnenii vozvrashaet 1, inache 0.

{UINT i,j,*e,*f,*g,h,p,*q,*r,*m,*n,*s,*u,*v;

  i = a[0]; j = b[0];
  i <<= 8;
  j <<= 8;
  i++; j++;
  g = F + 256;
  while(i >= j)
   {e = a + i;
    f = b + j;
    if(f[0] == 2 && f[2] == 1)
     {for(p = 0; p <= e[0]; p++)F[p] = e[p];
     }
    else
     {q = g + 256; r = g + 512; s = g + 768;
      u = g + 1024; v = g + 1280;
      for(p = 0; p <= e[0]; p++)q[p] = e[p];
      for(p = 0; p <= f[0]; p++)r[p] = f[p];
      q = nod96(q,r,F,g,s);
      s = (q == g ? r : g);
      for(p = 0; p <= f[0]; p++)u[p] = f[p];
      for(p = 0; p <= q[0]; p++)v[p] = q[p];
      delenie96(u,v,F,s);
      if(F[0] != 2 || F[2] != 1)
       {n = a + 1; m = e - 256;
        while(n != m)
         {h = umnog96(m,F,s);
          if(h != 0)return 1;
          for(p = 0; p <= s[0]; p++)m[p] = s[p];
          m -= 256;
         }
       }
      delenie96(e,q,F,s);
     }
    q = b + 1;
    i -= 256;e -= 256;
    f -= 256;
    while(f != q)
     {h = umnog96(F,f,g);
      if(h != 0)return 1;
      minus96(g);
      h = plus96(e,g);
      if(h != 0)return 1;
      e -= 256;
      f -= 256;
     }
    p = 1; e = a + i; f = a + 257;
    while(p == 1 && e != f)
     {if(e[0] == 2 && e[2] == 0)
       {i -= 256; e -= 256;}
      else p = 0;
     }
   }
  i--;
  i >>= 8;
  if(i == 0)
   {i = 1; a[257] = 2;
    a[258] = 0;
     a[259] = 0;
   }
  a[0] = i;
  normmn96(a);
  return 0;
 }


