inline i64 rd(){ i64 x = 0, f = 1, c = getchar(); while (((c - '0') | ('9' - c)) < 0) f = c != '-', c = getchar(); while (((c - '0') | ('9' - c)) > 0) x = x * 10 + c - '0', c = getchar(); return f ? x : -x; }
using i128 = __int128_t;
constint N = 100; const i128 P = 1000000000000000003; const i128 I2 = 500000000000000002;
int n; structele { int x, y, l; } a[N + 5]; int bx[N + 5], xc, by[N + 5], yc; i128 pw[N + 5], f[2][2][N + 5][N + 5];
intmain(){ n = rd(); for (int i = 1; i <= n; i++) { int x = rd(), y = rd(), l = rd(); a[i] = {x, y, l}, bx[i] = x, by[i] = y; } std::sort(bx + 1, bx + 1 + n), xc = std::unique(bx + 1, bx + 1 + n) - (bx + 1); std::sort(by + 1, by + 1 + n), yc = std::unique(by + 1, by + 1 + n) - (by + 1); std::sort(a + 1, a + 1 + n, [](ele a, ele b) { return a.x + a.y + a.l > b.x + b.y + b.l; }); for (int i = 1; i <= n; i++) a[i].x = std::lower_bound(bx + 1, bx + 1 + xc, a[i].x) - bx; for (int i = 1; i <= n; i++) a[i].y = std::lower_bound(by + 1, by + 1 + yc, a[i].y) - by;
i128 ans = 0;
f[0][0][0][0] = I2; for (int i = 1; i <= n; i++) { memset(f[i & 1], 0, sizeof(f[i & 1])); static i128 g[2][N + 5][N + 5]; memset(g, 0, sizeof(g)); for (int j = 0; j <= 1; j++) { for (int p = 0; p <= xc; p++) { int np = std::max(p, a[i].x); for (int q = 0; q <= yc; q++) { int nq = std::max(q, a[i].y); (f[i & 1][j][p][q] += f[(i - 1) & 1][j][p][q]) %= P; (f[i & 1][j][np][nq] += 2 * f[(i - 1) & 1][j ^ 1][p][q]) %= P; (g[j][np][nq] += 2 * f[(i - 1) & 1][j ^ 1][p][q]) %= P; } } } for (int j = 0; j <= 1; j++) { i128 tot = 0, L = bx[a[i].x] + by[a[i].y] + a[i].l; for (int p = 0; p <= xc; p++) { for (int q = 0; q <= yc; q++) { i128 l = std::max<i128>(0, L - bx[p] - by[q]); (tot += l * l % P * g[j][p][q] % P) %= P; } } (ans += (!j) ? P - tot : tot) %= P; } }