#include using namespace std; const long long INF = 2000000001; const long long MOD = 1000000007; template struct segment_tree_2d{ vector> pos; vector X; vector> Y; int N; vector N2; vector> ST; function f; T E; segment_tree_2d(function f, T E): f(f), E(E){ } void add(int x, int y){ pos.push_back(make_pair(x, y)); X.push_back(x); } void build(){ int cnt = pos.size(); sort(X.begin(), X.end()); X.erase(unique(X.begin(), X.end()), X.end()); int cnt2 = X.size(); N = 1; while (N < cnt2){ N *= 2; } Y = vector>(N * 2 - 1); for (int i = 0; i < cnt; i++){ int p = lower_bound(X.begin(), X.end(), pos[i].first) - X.begin(); p += N - 1; Y[p].push_back(pos[i].second); while (p > 0){ p = (p - 1) / 2; Y[p].push_back(pos[i].second); } } N2 = vector(N * 2 - 1, 0); ST = vector>(N * 2 - 1); for (int i = 0; i < N * 2 - 1; i++){ if (!Y[i].empty()){ sort(Y[i].begin(), Y[i].end()); Y[i].erase(unique(Y[i].begin(), Y[i].end()), Y[i].end()); int cnt3 = Y[i].size(); N2[i] = 1; while (N2[i] < cnt3){ N2[i] *= 2; } ST[i] = vector(N2[i] * 2 - 1); } } } T get(int x, int y){ int p1 = lower_bound(X.begin(), X.end(), x) - X.begin(); p1 += N - 1; int p2 = lower_bound(Y[p1].begin(), Y[p1].end(), y) - Y[p1].begin(); p2 += N2[p1] - 1; return ST[p1][p2]; } void update2(int i, int j, T x){ j += N2[i] - 1; ST[i][j] = x; while (j > 0){ j = (j - 1) / 2; ST[i][j] = f(ST[i][j * 2 + 1], ST[i][j * 2 + 2]); } } void update(int i, int j, T x){ int p1 = lower_bound(X.begin(), X.end(), i) - X.begin(); p1 += N - 1; int p2 = lower_bound(Y[p1].begin(), Y[p1].end(), j) - Y[p1].begin(); update2(p1, p2, x); while (p1 > 0){ p1 = (p1 - 1) / 2; p2 = lower_bound(Y[p1].begin(), Y[p1].end(), j) - Y[p1].begin(); T x2 = 0; int pl = lower_bound(Y[p1 * 2 + 1].begin(), Y[p1 * 2 + 1].end(), j) - Y[p1 * 2 + 1].begin(); if (pl < Y[p1 * 2 + 1].size()){ if (Y[p1 * 2 + 1][pl] == j){ x2 += ST[p1 * 2 + 1][N2[p1 * 2 + 1] - 1 + pl]; } } int pr = lower_bound(Y[p1 * 2 + 2].begin(), Y[p1 * 2 + 2].end(), j) - Y[p1 * 2 + 2].begin(); if (pr < Y[p1 * 2 + 2].size()){ if (Y[p1 * 2 + 2][pr] == j){ x2 += ST[p1 * 2 + 2][N2[p1 * 2 + 2] - 1 + pr]; } } update2(p1, p2, x2); } } T query1(int id, int L, int R, int i, int l, int r){ if (r <= L || R <= l){ return E; } else if (L <= l && r <= R){ return ST[id][i]; } else { int m = (l + r) / 2; return f(query1(id, L, R, i * 2 + 1, l, m), query1(id, L, R, i * 2 + 2, m, r)); } } T query2(int U, int D, int L, int R, int i, int u, int d){ if (d <= U || D <= u){ return E; } else if (U <= u && d <= D){ int l = lower_bound(Y[i].begin(), Y[i].end(), L) - Y[i].begin(); int r = lower_bound(Y[i].begin(), Y[i].end(), R) - Y[i].begin(); return query1(i, l, r, 0, 0, N2[i]); } else { int m = (u + d) / 2; return f(query2(U, D, L, R, i * 2 + 1, u, m), query2(U, D, L, R, i * 2 + 2, m, d)); } } T query(int U, int D, int L, int R){ int u = lower_bound(X.begin(), X.end(), U) - X.begin(); int d = lower_bound(X.begin(), X.end(), D) - X.begin(); return query2(u, d, L, R, 0, 0, N); } }; int op(int x, int y){ return x + y; } int main(){ int N; cin >> N; vector a(N); for (int i = 0; i < N; i++){ cin >> a[i]; } vector b(N); for (int i = 0; i < N; i++){ cin >> b[i]; } vector ans(2, 0); for (int i = 0; i < 2; i++){ vector> P(N); for (int j = 0; j < N; j++){ P[j] = make_pair(a[j], b[j]); } sort(P.begin(), P.end()); for (int j = 0; j < N; j++){ a[j] = P[j].first; b[j] = P[j].second; } vector> P2(N); for (int j = 0; j < N; j++){ P2[j] = make_pair(b[j], j); } sort(P2.begin(), P2.end()); vector id(N); for (int j = 0; j < N; j++){ id[j] = P2[j].second; } segment_tree_2d ST1(op, 0); segment_tree_2d ST2(op, 0); for (int j = 0; j < N; j++){ ST1.add(j, a[j] - b[j]); ST2.add(j, a[j] + b[j]); } ST1.build(); ST2.build(); for (int j = 0; j < N; j++){ int p = id[j]; int cnt1 = ST1.query(0, p, -INF, a[p] - b[p]); ans[i] += (long long) a[p] * cnt1 % MOD; int cnt2 = ST2.query(p + 1, N, a[p] + b[p] + 1, INF); ans[i] += MOD - (long long) a[p] * cnt2 % MOD; ST1.update(p, a[p] - b[p], 1); ST2.update(p, a[p] + b[p], 1); } for (int j = 0; j < N; j++){ ST1.update(j, a[j] - b[j], 0); ST2.update(j, a[j] + b[j], 0); } for (int j = N - 1; j >= 0; j--){ int p = id[j]; int cnt1 = ST2.query(0, p, -INF, a[p] + b[p]); ans[i] += (long long) a[p] * cnt1 % MOD; int cnt2 = ST1.query(p + 1, N, a[p] - b[p] + 1, INF); ans[i] += MOD - (long long) a[p] * cnt2 % MOD; ST1.update(p, a[p] - b[p], 1); ST2.update(p, a[p] + b[p], 1); } ans[i] %= MOD; ans[i] += MOD; ans[i] *= 2; ans[i] %= MOD; swap(a, b); } cout << ans[0] << ' ' << ans[1] << endl; }