import scala.
collection.
mutable.
{HashMap
=> HMap
}
def gcd
(a
:Int, b
:Int
):Int
= { }
val numer
: Int
= n/gcd
(n,d
)*sgn
(d
) val denom
: Int
= d/gcd
(n,d
)*sgn
(d
) def isZero
: Boolean
= (n
==0) def compare
(that
:Rational
):Int
= numer
*that.
denom - denom
*that.
numer def equals
(that
:Rational
) = numer
*that.
denom == denom
*that.
numer def +
(rhs
:Rational
):Rational
= Rational
(numer
*rhs.
denom + denom
*rhs.
numer, denom
*rhs.
denom) def -
(rhs
:Rational
):Rational
= Rational
(numer
*rhs.
denom - denom
*rhs.
numer, denom
*rhs.
denom) def *(rhs
:Rational
):Rational
= Rational
(numer
*rhs.
numer, denom
*rhs.
denom) def /
(rhs
:Rational
):Rational
= Rational
(numer
*rhs.
denom, denom
*rhs.
numer) def unary
_-
: Rational
= Rational
(-numer,denom
) }
def apply
(n
: Int, nx
: Int, ny
:Int
) = Mono2
(Rational
(n,
1), nx, ny
) def *(rhs
:Mono2
):Mono2
= Mono2
(c
*rhs.
c, degX+rhs.
degX, degY+rhs.
degY) def isZero
: Boolean
= c.
isZero def totalDeg
: Int
= degX+degY
def compare
(that
: Mono2
):Int
= grlex
(that
) def lex
(that
: Mono2
): Int
= if (degX
==that.
degX) degY-that.
degY else degX-that.
degX def grlex
(that
:Mono2
): Int
= if (totalDeg
==that.
totalDeg) degX-that.
degX else totalDeg-that.
totalDeg def grevlex
(that
:Mono2
): Int
= if (totalDeg
==that.
totalDeg) -
(degY-that.
degY) else totalDeg-that.
totalDeg (if (degX
==0) "" else if (degX
==1) "x" else "x^"+degX.
toString) +
(if (degY
==0) "" else if (degY
==1) "y" else "y^"+degY.
toString) def /
(rhs
:Mono2
): Option
[Mono2
] = if (rhs.
degX <= degX
&& rhs.
degY <= degY
) Some
(Mono2
(c/rhs.
c, degX-rhs.
degX, degY-rhs.
degY)) else None
}
val monos
: List
[Mono2
] = normalize
(xs
) def compare
(that
:Poly2
): Int
= (monos, that.
monos) match { case _ => monos.
head.
compare(that.
monos.
head) }
def isZero
:Boolean
= monos.
length == 0 def multideg
:(Int,Int
) = monos.
head match {case Mono2
(_,nx,ny
) => (nx,ny
)} def lc
: Rational
= monos.
head match {case Mono2
(c,
_,
_) => c
} def lm
: Mono2
= monos.
head match {case Mono2
(c,nx,ny
) => Mono2
(Rational
(1,
1),nx,ny
)} def lt
: Mono2
= monos.
head def normalize
(xs
: List
[Mono2
]): List
[Mono2
] = { val m
: HMap
[(Int,Int
),Rational
] = HMap.
empty xs.
foreach {case Mono2
(c,nx,ny
) => { case None
=> m
((nx,ny
)) = c
case Some
(c1
) => m
((nx,ny
)) = c + c1
}
}}
m.
toList.
map{case ((nx,ny
),c
) => Mono2
(c,nx,ny
)}.
filter{m
=> !(m.
isZero)}.
sorted.
reverse }
def +
(rhs
:Poly2
):Poly2
= { Poly2(normalize(monos++rhs.monos))
}
def -
(rhs
:Poly2
):Poly2
= { Poly2
(normalize
(monos++ rhs.
monos.
map{case Mono2
(c,nx,ny
) => Mono2
(-c,nx,ny
)})) }
def *(rhs
:Poly2
):Poly2
= { Poly2(normalize(
for(Mono2
(c1,nx1,ny1
) <- monos
; Mono2
(c2,nx2,ny2
) <- rhs.
monos) yield Mono2
(c1
*c2, nx1+nx2, ny1+ny2
) ))
}
def *(rhs
:Mono2
):Poly2
= if (rhs.
isZero) Poly2
(List
(Mono2
(Rational
(0,
1),
0,
0))) else { Poly2
(monos.
map{case Mono2
(c,nx,ny
) => Mono2
(c
*rhs.
c, nx+rhs.
degX, ny+rhs.
degY)}) }
def divMod
(rhs
:Poly2
): (Poly2,Poly2
) = { val (p1,q1
) = (this-rhs
*p
).
divMod(rhs
) (Poly2(p::Nil)+p1,q1)
}
}
}
}
def divMod
(fs
: List
[Poly2
]): (List
[Poly2
],Poly2
) = { val aa
:Array
[Poly2
] = fs.
map{f
=> Poly2
(Nil
)}.
toArray var rr
:Poly2
= Poly2
(Nil
) while(i
< fs.
length && !dived
) { (pp.
lt / fs
(i
).
lt) match { case Some
(t
) => {aa
(i
) = aa
(i
) + Poly2
(List
(t
)); pp
= pp - fs
(i
)*t
; dived
= true} }
}
if (!dived
) {rr
= rr + Poly2
(List
(pp.
lt)); pp
= Poly2
(pp.
monos.
tail)} }
(aa.toList,rr)
}
}
implicit def toRational
(n
:Int
): Rational
= Rational
(n,
1) def main
(args
: Array
[String
]) = { val f
= Poly2
(List
(Mono2
(1,
7,
2), Mono2
(1,
3,
2), Mono2
(-
1,
0,
1), Mono2
(1,
0,
0))) val f1
= Poly2
(List
(Mono2
(1,
1,
2),Mono2
(-
1,
1,
0)))//> f1 : foo.Poly2 = 1xy^2+-1x val f2
= Poly2
(List
(Mono2
(1,
1,
0),Mono2
(-
1,
0,
3)))//> f2 : foo.Poly2 = -1y^3+1x println(f divMod List(f1,f2))
println(f divMod List(f2,f1))
}
}
aW1wb3J0IHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS57SGFzaE1hcCA9PiBITWFwfQoKY2FzZSBjbGFzcyBSYXRpb25hbChuOiBJbnQsIGQ6IEludCkgZXh0ZW5kcyBPcmRlcmVkW1JhdGlvbmFsXSB7CiAgZGVmIGdjZChhOkludCwgYjpJbnQpOkludCA9IHsKICAgIGlmIChhID09IDApIGIKICAgIGVsc2UgaWYgKGIgPT0gMCkgYQogICAgZWxzZSBpZiAoYSA8IDApIGdjZCgtYSxiKQogICAgZWxzZSBpZiAoYiA8IDApIGdjZChhLC1iKQogICAgZWxzZSBpZiAoYTxiKSBnY2QoYixhKQogICAgZWxzZSBnY2QoYiwgYSViKQogIH0KICBkZWYgc2duKGE6SW50KSA9IGlmIChhIDwgMCkgLTEgZWxzZSBpZiAoYSA+IDApIDEgZWxzZSAwCiAgdmFsIG51bWVyOiBJbnQgPSBuL2djZChuLGQpKnNnbihkKQogIHZhbCBkZW5vbTogSW50ID0gZC9nY2QobixkKSpzZ24oZCkKICBkZWYgaXNaZXJvOiBCb29sZWFuID0gKG49PTApCiAgZGVmIGNvbXBhcmUodGhhdDpSYXRpb25hbCk6SW50ID0gbnVtZXIqdGhhdC5kZW5vbSAtIGRlbm9tKnRoYXQubnVtZXIKICBkZWYgZXF1YWxzKHRoYXQ6UmF0aW9uYWwpID0gbnVtZXIqdGhhdC5kZW5vbSA9PSBkZW5vbSp0aGF0Lm51bWVyCiAgZGVmICsocmhzOlJhdGlvbmFsKTpSYXRpb25hbCA9IFJhdGlvbmFsKG51bWVyKnJocy5kZW5vbSArIGRlbm9tKnJocy5udW1lciwgZGVub20qcmhzLmRlbm9tKQogIGRlZiAtKHJoczpSYXRpb25hbCk6UmF0aW9uYWwgPSBSYXRpb25hbChudW1lcipyaHMuZGVub20gLSBkZW5vbSpyaHMubnVtZXIsIGRlbm9tKnJocy5kZW5vbSkKICBkZWYgKihyaHM6UmF0aW9uYWwpOlJhdGlvbmFsID0gUmF0aW9uYWwobnVtZXIqcmhzLm51bWVyLCBkZW5vbSpyaHMuZGVub20pCiAgZGVmIC8ocmhzOlJhdGlvbmFsKTpSYXRpb25hbCA9IFJhdGlvbmFsKG51bWVyKnJocy5kZW5vbSwgZGVub20qcmhzLm51bWVyKQogIG92ZXJyaWRlIGRlZiB0b1N0cmluZyA9IGlmIChkZW5vbT09MSkgbnVtZXIudG9TdHJpbmcgZWxzZSBzIiR7bnVtZXJ9LyR7ZGVub219IgogIGRlZiB1bmFyeV8tIDogUmF0aW9uYWwgPSBSYXRpb25hbCgtbnVtZXIsZGVub20pCn0KY2FzZSBjbGFzcyBNb25vMih2YWwgYzogUmF0aW9uYWwsIHZhbCBkZWdYOiBJbnQsIHZhbCBkZWdZOiBJbnQpIGV4dGVuZHMgT3JkZXJlZFtNb25vMl17CiAgZGVmIGFwcGx5KG46IEludCwgbng6IEludCwgbnk6SW50KSA9IE1vbm8yKFJhdGlvbmFsKG4sMSksIG54LCBueSkKICBkZWYgKihyaHM6TW9ubzIpOk1vbm8yID0gTW9ubzIoYypyaHMuYywgZGVnWCtyaHMuZGVnWCwgZGVnWStyaHMuZGVnWSkKICBkZWYgaXNaZXJvOiBCb29sZWFuID0gYy5pc1plcm8KICBkZWYgdG90YWxEZWc6IEludCA9IGRlZ1grZGVnWQogIGRlZiBjb21wYXJlKHRoYXQ6IE1vbm8yKTpJbnQgPSBncmxleCh0aGF0KQogIGRlZiBsZXgodGhhdDogTW9ubzIpOiBJbnQgPSBpZiAoZGVnWD09dGhhdC5kZWdYKSBkZWdZLXRoYXQuZGVnWSBlbHNlIGRlZ1gtdGhhdC5kZWdYCiAgZGVmIGdybGV4KHRoYXQ6TW9ubzIpOiBJbnQgPSBpZiAodG90YWxEZWc9PXRoYXQudG90YWxEZWcpIGRlZ1gtdGhhdC5kZWdYIGVsc2UgdG90YWxEZWctdGhhdC50b3RhbERlZwogIGRlZiBncmV2bGV4KHRoYXQ6TW9ubzIpOiBJbnQgPSBpZiAodG90YWxEZWc9PXRoYXQudG90YWxEZWcpIC0oZGVnWS10aGF0LmRlZ1kpIGVsc2UgdG90YWxEZWctdGhhdC50b3RhbERlZwogIG92ZXJyaWRlIGRlZiB0b1N0cmluZyA9KGMudG9TdHJpbmcpICsKICAgIChpZiAoZGVnWD09MCkgIiIgZWxzZSBpZiAoZGVnWD09MSkgIngiIGVsc2UgInheIitkZWdYLnRvU3RyaW5nKSArCiAgICAoaWYgKGRlZ1k9PTApICIiIGVsc2UgaWYgKGRlZ1k9PTEpICJ5IiBlbHNlICJ5XiIrZGVnWS50b1N0cmluZykKICBkZWYgLyhyaHM6TW9ubzIpOiBPcHRpb25bTW9ubzJdID0gaWYgKHJocy5kZWdYIDw9IGRlZ1ggJiYgcmhzLmRlZ1kgPD0gZGVnWSkgU29tZShNb25vMihjL3Jocy5jLCBkZWdYLXJocy5kZWdYLCBkZWdZLXJocy5kZWdZKSkgZWxzZSBOb25lCn0KY2FzZSBjbGFzcyBQb2x5Mih4czogTGlzdFtNb25vMl0pIGV4dGVuZHMgT3JkZXJlZFtQb2x5Ml0gewogIHZhbCBtb25vczogTGlzdFtNb25vMl0gPSBub3JtYWxpemUoeHMpCiAgZGVmIGNvbXBhcmUodGhhdDpQb2x5Mik6IEludCA9IChtb25vcywgdGhhdC5tb25vcykgbWF0Y2ggewogICAgY2FzZSAoTmlsLE5pbCkgPT4gMAogICAgY2FzZSAoTmlsLF8pID0+IC0xCiAgICBjYXNlIChfLE5pbCkgPT4gMQogICAgY2FzZSBfID0+IG1vbm9zLmhlYWQuY29tcGFyZSh0aGF0Lm1vbm9zLmhlYWQpCiAgfQogIG92ZXJyaWRlIGRlZiB0b1N0cmluZyA9IG1vbm9zLm1rU3RyaW5nKCIrIikKICBkZWYgaXNaZXJvOkJvb2xlYW4gPSBtb25vcy5sZW5ndGggPT0gMAogIGRlZiBtdWx0aWRlZzooSW50LEludCkgPSBtb25vcy5oZWFkIG1hdGNoIHtjYXNlIE1vbm8yKF8sbngsbnkpID0+IChueCxueSl9CiAgZGVmIGxjOiBSYXRpb25hbCA9IG1vbm9zLmhlYWQgbWF0Y2gge2Nhc2UgTW9ubzIoYyxfLF8pID0+IGN9CiAgZGVmIGxtOiBNb25vMiA9IG1vbm9zLmhlYWQgbWF0Y2gge2Nhc2UgTW9ubzIoYyxueCxueSkgPT4gTW9ubzIoUmF0aW9uYWwoMSwxKSxueCxueSl9CiAgZGVmIGx0OiBNb25vMiA9IG1vbm9zLmhlYWQKICBkZWYgbm9ybWFsaXplKHhzOiBMaXN0W01vbm8yXSk6IExpc3RbTW9ubzJdID0gewogICAgdmFsIG06IEhNYXBbKEludCxJbnQpLFJhdGlvbmFsXSA9IEhNYXAuZW1wdHkKICAgIHhzLmZvcmVhY2gge2Nhc2UgTW9ubzIoYyxueCxueSkgPT4gewogICAgICBtLmdldCgobngsbnkpKSBtYXRjaCB7CiAgICAgICAgY2FzZSBOb25lID0+IG0oKG54LG55KSkgPSBjCiAgICAgICAgY2FzZSBTb21lKGMxKSA9PiBtKChueCxueSkpID0gYyArIGMxCiAgICAgIH0KICAgIH19CiAgICBtLnRvTGlzdC5tYXB7Y2FzZSAoKG54LG55KSxjKSA9PiBNb25vMihjLG54LG55KX0uZmlsdGVye20gPT4gIShtLmlzWmVybyl9LnNvcnRlZC5yZXZlcnNlCiAgfQogIGRlZiArKHJoczpQb2x5Mik6UG9seTIgPSB7CiAgICBQb2x5Mihub3JtYWxpemUobW9ub3MrK3Jocy5tb25vcykpCiAgfQogIGRlZiAtKHJoczpQb2x5Mik6UG9seTIgPSB7CiAgICBQb2x5Mihub3JtYWxpemUobW9ub3MrKyByaHMubW9ub3MubWFwe2Nhc2UgTW9ubzIoYyxueCxueSkgPT4gTW9ubzIoLWMsbngsbnkpfSkpCiAgfQogIGRlZiAqKHJoczpQb2x5Mik6UG9seTIgPSB7CiAgICBQb2x5Mihub3JtYWxpemUoCiAgICAgIGZvcihNb25vMihjMSxueDEsbnkxKSA8LSBtb25vczsgTW9ubzIoYzIsbngyLG55MikgPC0gcmhzLm1vbm9zKQogICAgICB5aWVsZCBNb25vMihjMSpjMiwgbngxK254MiwgbnkxK255MikKICAgICkpCiAgfQogIGRlZiAqKHJoczpNb25vMik6UG9seTIgPSBpZiAocmhzLmlzWmVybykgUG9seTIoTGlzdChNb25vMihSYXRpb25hbCgwLDEpLDAsMCkpKSBlbHNlIHsKICAgIFBvbHkyKG1vbm9zLm1hcHtjYXNlIE1vbm8yKGMsbngsbnkpID0+IE1vbm8yKGMqcmhzLmMsIG54K3Jocy5kZWdYLCBueStyaHMuZGVnWSl9KQogIH0KICBkZWYgZGl2TW9kKHJoczpQb2x5Mik6IChQb2x5MixQb2x5MikgPSB7CiAgICBpZiAoaXNaZXJvKSAodGhpcywgcmhzKQogICAgZWxzZSBpZiAocmhzLmlzWmVybykgdGhyb3cgbmV3IEV4Y2VwdGlvbigiZGl2IGJ5IHplcm8iKQogICAgZWxzZSB7CiAgICAgIChsdCAvIHJocy5sdCkgbWF0Y2ggewogICAgICAgIGNhc2UgTm9uZSA9PiAoUG9seTIoTmlsKSwgdGhpcykKICAgICAgICBjYXNlIFNvbWUocCkgPT4gewogICAgICAgICAgdmFsIChwMSxxMSkgPSAodGhpcy1yaHMqcCkuZGl2TW9kKHJocykKICAgICAgICAgIChQb2x5MihwOjpOaWwpK3AxLHExKQogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBkZWYgZGl2TW9kKGZzOiBMaXN0W1BvbHkyXSk6IChMaXN0W1BvbHkyXSxQb2x5MikgPSB7CiAgICB2YWwgYWE6QXJyYXlbUG9seTJdID0gZnMubWFwe2YgPT4gUG9seTIoTmlsKX0udG9BcnJheQogICAgdmFyIHJyOlBvbHkyID0gUG9seTIoTmlsKQogICAgdmFyIHBwOlBvbHkyID0gdGhpcwogICAgd2hpbGUoIShwcC5pc1plcm8pKSB7CiAgICAgIHZhciBkaXZlZDpCb29sZWFuID0gZmFsc2UKICAgICAgdmFyIGkgPSAwCiAgICAgIHdoaWxlKGkgPCBmcy5sZW5ndGggJiYgIWRpdmVkKSB7CiAgICAgICAgKHBwLmx0IC8gZnMoaSkubHQpIG1hdGNoIHsKICAgICAgICAgIGNhc2UgU29tZSh0KSA9PiB7YWEoaSkgPSBhYShpKSArIFBvbHkyKExpc3QodCkpOyBwcCA9IHBwIC0gZnMoaSkqdDsgZGl2ZWQgPSB0cnVlfQogICAgICAgICAgY2FzZSBOb25lID0+IHtpICs9IDF9CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICghZGl2ZWQpIHtyciA9IHJyICsgUG9seTIoTGlzdChwcC5sdCkpOyBwcCA9IFBvbHkyKHBwLm1vbm9zLnRhaWwpfQogICAgfQogICAgKGFhLnRvTGlzdCxycikKICB9Cn0Kb2JqZWN0IE1haW4gewogIGltcGxpY2l0IGRlZiB0b1JhdGlvbmFsKG46SW50KTogUmF0aW9uYWwgPSBSYXRpb25hbChuLDEpCiAgZGVmIG1haW4oYXJnczogQXJyYXlbU3RyaW5nXSkgPSB7CiAgICB2YWwgZiA9IFBvbHkyKExpc3QoTW9ubzIoMSw3LDIpLCBNb25vMigxLDMsMiksIE1vbm8yKC0xLDAsMSksIE1vbm8yKDEsMCwwKSkpCiAgICB2YWwgZjEgPSBQb2x5MihMaXN0KE1vbm8yKDEsMSwyKSxNb25vMigtMSwxLDApKSkvLz4gZjEgIDogZm9vLlBvbHkyID0gMXh5XjIrLTF4CiAgICB2YWwgZjIgPSBQb2x5MihMaXN0KE1vbm8yKDEsMSwwKSxNb25vMigtMSwwLDMpKSkvLz4gZjIgIDogZm9vLlBvbHkyID0gLTF5XjMrMXgKICAJcHJpbnRsbihmIGRpdk1vZCBMaXN0KGYxLGYyKSkKICAJcHJpbnRsbihmIGRpdk1vZCBMaXN0KGYyLGYxKSkKICB9Cn0=