structFrac { LL x, y; int id; Frac operator +(Frac t) const { return {x + t.x, y + t.y}; } booloperator <(Frac t) const { return (s128) x * t.y < (s128) y * t.x; } booloperator >(Frac t) const { return (s128) x * t.y > (s128) y * t.x; } booloperator ==(Frac t) const { return x == t.x && y == t.y; } Frac operator *(LL t) const { return {x * t, y * t}; } } a[N];
voidinsert(int id, int x) { auto iter = s[id].insert(x).first; int y = *std::prev(iter), z = *std::next(iter); ans[id] = (ans[id] + (LL) (z - x) * (x - y)) % Mod; }
intsolve(int l, int r, Frac lf, Frac rf) { while (l <= n && a[l] == lf) l ++; while (r && a[r] == rf) r --; if (l > r) return1; int cnt = 1; if (a[r] < lf + rf) { int x = 2, y = 1e9; while (x < y) { int mid = (x + y + 1) >> 1; if (lf * mid + rf > a[r]) x = mid; else y = mid - 1; } rf = rf + lf * (x - 1), cnt = x; } elseif (a[l] > lf + rf) { int x = 2, y = 1e9; while (x < y) { int mid = (x + y + 1) >> 1; if (lf + rf * mid < a[l]) x = mid; else y = mid - 1; } lf = lf + rf * (x - 1), cnt = x; } int x = l, y = r + 1, mL, mR; while (x < y) { int mid = (x + y) >> 1; if (a[mid] < lf + rf) x = mid + 1; else y = mid; } mL = x, x = l - 1, y = r; while (x < y) { int mid = (x + y + 1) >> 1; if (a[mid] > lf + rf) y = mid - 1; else x = mid; } mR = x; // Equal (a + c) / (b + d) range int lc = solve(l, mL - 1, lf, lf + rf), rc = solve(mR + 1, r, lf + rf, rf); if (s[lc].size() > s[rc].size()) std::swap(lc, rc); if (rc == 1) s[rc = ++ tot] = {0, n + 1}; for (int t : s[lc]) if (t >= 1 && t <= n) insert(rc, t); for (int t = mL; t <= mR; ++ t) insert(rc, a[t].id); res = (res + (LL) ans[rc] * cnt) % Mod; return rc; }
intwork(std::vector<Frac> vec) { res = 0; n = vec.size(); for (int i = 0; i < n; ++ i) a[i + 1] = vec[i], a[i + 1].id = i + 1; std::sort(a + 1, a + n + 1); s[1] = {0, n + 1}; returnsolve(1, n, {0, 1}, {1, 0}), res; }