#include <algorithm> #include <cstdio> #include <set> #include <vector> typedef long long int i64; const i64 MOD = 1000000007; struct Shelf { int left, right; std::set<int> connections; } shelves[500500]; inline bool between(int middle, Shelf &s) { return s.left < middle && middle < s.right; } int sim(std::vector<int> &order) { auto N = order.size(); int res = 0; std::set<int> sunken; for (int k : order) { if (sunken.insert(k).second) { ++res; for (int n : shelves[k].connections) { sunken.insert(n); } if (sunken.size() == N) { break; } } } return res; } i64 nwd(i64 a, i64 b) { if (a % b == 0) { return b; } return nwd(b, a % b); } inline void swap(i64 &a, i64 &b) { i64 t = a; a = b; b = t; } i64 inv(i64 a, i64 mod) { i64 u = 1, w = a, x = 0, z = mod, q; while (w != 0) { if (w < z) { swap(u, x); swap(w, z); } q = w / z; u = u - q * x; w = w - q * z; } if (x < 0) { x = x + mod; } return x; } i64 frac(i64 sum, i64 opts) { i64 nn = nwd(sum, opts); sum /= nn; opts /= nn; if (opts == 1) { return sum; } else { i64 in = inv(opts, MOD); return (in * sum) % MOD; } } int main() { // printf("%lld\n", inv(30, MOD)); // exit(0); int N; std::vector<int> order; scanf("%d", &N); for (int i = 0; i < N; ++i) { order.push_back(i); int cl, cr; scanf("%d%d", &cl, &cr); shelves[i].left = cl; shelves[i].right = cr; bool left_used = false, right_used = false; for (int j = i - 1; j >= 0; --j) { if (!left_used && between(cl, shelves[j])) { left_used = true; shelves[i].connections.insert(j); for (int next : shelves[j].connections) { shelves[i].connections.insert(next); } } if (!right_used && between(cr, shelves[j])) { right_used = true; shelves[i].connections.insert(j); for (int next : shelves[j].connections) { shelves[i].connections.insert(next); } } } } // for (int i = 0; i < N; ++i) { // printf("%d: ", i + 1); // for (int c : shelves[i].connections) { // printf("%d ", c + 1); // } // puts(""); // } i64 sum = 0; i64 opts = 0; do { ++opts; sum += sim(order); // for (int x : order) { // printf("%d ", x + 1); // } // printf(" -> %d\n", sim(order)); } while (std::next_permutation(order.begin(), order.end())); printf("%lld\n", frac(sum, opts)); return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #include <algorithm> #include <cstdio> #include <set> #include <vector> typedef long long int i64; const i64 MOD = 1000000007; struct Shelf { int left, right; std::set<int> connections; } shelves[500500]; inline bool between(int middle, Shelf &s) { return s.left < middle && middle < s.right; } int sim(std::vector<int> &order) { auto N = order.size(); int res = 0; std::set<int> sunken; for (int k : order) { if (sunken.insert(k).second) { ++res; for (int n : shelves[k].connections) { sunken.insert(n); } if (sunken.size() == N) { break; } } } return res; } i64 nwd(i64 a, i64 b) { if (a % b == 0) { return b; } return nwd(b, a % b); } inline void swap(i64 &a, i64 &b) { i64 t = a; a = b; b = t; } i64 inv(i64 a, i64 mod) { i64 u = 1, w = a, x = 0, z = mod, q; while (w != 0) { if (w < z) { swap(u, x); swap(w, z); } q = w / z; u = u - q * x; w = w - q * z; } if (x < 0) { x = x + mod; } return x; } i64 frac(i64 sum, i64 opts) { i64 nn = nwd(sum, opts); sum /= nn; opts /= nn; if (opts == 1) { return sum; } else { i64 in = inv(opts, MOD); return (in * sum) % MOD; } } int main() { // printf("%lld\n", inv(30, MOD)); // exit(0); int N; std::vector<int> order; scanf("%d", &N); for (int i = 0; i < N; ++i) { order.push_back(i); int cl, cr; scanf("%d%d", &cl, &cr); shelves[i].left = cl; shelves[i].right = cr; bool left_used = false, right_used = false; for (int j = i - 1; j >= 0; --j) { if (!left_used && between(cl, shelves[j])) { left_used = true; shelves[i].connections.insert(j); for (int next : shelves[j].connections) { shelves[i].connections.insert(next); } } if (!right_used && between(cr, shelves[j])) { right_used = true; shelves[i].connections.insert(j); for (int next : shelves[j].connections) { shelves[i].connections.insert(next); } } } } // for (int i = 0; i < N; ++i) { // printf("%d: ", i + 1); // for (int c : shelves[i].connections) { // printf("%d ", c + 1); // } // puts(""); // } i64 sum = 0; i64 opts = 0; do { ++opts; sum += sim(order); // for (int x : order) { // printf("%d ", x + 1); // } // printf(" -> %d\n", sim(order)); } while (std::next_permutation(order.begin(), order.end())); printf("%lld\n", frac(sum, opts)); return 0; } |