#include struct term { int c, x, y, w, z; }; struct term read_term() { struct term term; term.c = term.x = term.y = term.w = term.z = 0; scanf("%d", &term.c); for (;;) { int p; char v; int n = scanf(" %c", &v); if (n != 1 || v == '.') break; scanf("%d", &p); if (v == 'x') term.x += p; else if (v == 'y') term.y += p; else if (v == 'w') term.w += p; else if (v == 'z') term.z += p; } return term; } void print_vp(char name, int p) { if (p == 1) printf("%c", name); else if (p > 1) printf("%c%d", name, p); } void write_term(struct term term) { if (term.c == 0) return; if (term.c != 1 || term.x + term.y + term.z + term.w == 0) printf("%d", term.c); print_vp('x', term.x); print_vp('y', term.y); print_vp('w', term.w); print_vp('z', term.z); } int term_cmp(struct term a, struct term b) { if (a.x < b.x) return -1; else if (a.x > b.x) return 1; if (a.y < b.y) return -1; else if (a.y > b.y) return 1; if (a.w < b.w) return -1; else if (a.w > b.w) return 1; if (a.z < b.z) return -1; else if (a.z > b.z) return 1; if (a.c < b.c) return -1; else if (a.c > b.c) return 1; return 0; } int term_like(struct term a, struct term b) { return a.x == b.x && a.y == b.y && a.w == b.w && a.z == b.z; } int min_term(int n, struct term *poly) { int min = 0; for (int i = 1; i < n; i++) if (term_cmp(poly[i], poly[min]) < 0) min = i; return min; } int read_poly(struct term *poly) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) poly[i] = read_term(); return n; } void rec_write_poly(int first, int n, struct term *poly) { if (n == 0) return; int min = min_term(n, poly); if (!first && poly[min].c > 0) printf("+"); write_term(poly[min]); poly[min] = poly[n - 1]; rec_write_poly(0, n - 1, poly); } void write_poly(int n, struct term *poly) { if (n == 0) printf("0\n"); else { struct term copy[n]; for (int i = 0; i < n; i++) copy[i] = poly[i]; rec_write_poly(1, n, copy); } } int simplify_poly(int n, struct term *poly) { int i = 0; while (i < n -1) { int j = i + 1; while (j < n) if (term_like(poly[i], poly[j])) { poly[i].c += poly[j].c; poly[j] = poly[--n]; } else j++; if (poly[i].c == 0) if (i < n - 1) poly[i] = poly[--n]; else n--; else i++; } return n; } int sum_poly(int n, struct term *p, int m, struct term *q, struct term *s) { struct term t[n + m]; for (int i = 0; i < n; i++) t[i] = p[i]; for (int i = 0; i < m; i++) t[i + n] = q[i]; for (int i = 0; i < m + n; i ++) s[i] = t[i]; return simplify_poly(n + m, s); } struct term mult_term(struct term p, struct term q) { struct term s; s.c = p.c * q.c; s.x = p.x + q.x; s.y = p.y + q.y; s.w = p.w + q.w; s.z = p.z + q.z; return s; } int mult_poly(int np, struct term *p, int nq, struct term *q, struct term *s) { int ns = 0; for (int j = 0; j < nq; j++) { struct term t[np]; for (int i = 0; i < np; i++) t[i] = mult_term(p[i], q[j]); ns = sum_poly(np, t, ns, s, s); } return ns; } int main(void) { int np, nq, ns; struct term p[100], q[100], s[100]; for (;;) { char ch; scanf(" %c", &ch); if (ch == '.') break; switch (ch) { case 'T': write_term(read_term()); putchar('\n'); break; case 'S': np = read_poly(p); np = simplify_poly(np, p); write_poly(np, p); putchar('\n'); break; case '+': np = read_poly(p); nq = read_poly(q); ns = sum_poly(np, p, nq, q, s); write_poly(ns, s); putchar('\n'); break; case '*': np = read_poly(p); nq = read_poly(q); ns = mult_poly(np, p, nq, q, s); write_poly(ns, s); putchar('\n'); break; } } return 0; }