#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#define ll unsigned long long
using namespace std;
int base = 1;
void update(int l, int r, int x, vector <int> &drzewo){
l += base - 1;
r += base + 1;
while (l/2 != r/2){
if (l % 2 == 0){
drzewo[l+1] = x;
}
if (r % 2 == 1){
drzewo[r-1] = x;
}
l /= 2;
r /= 2;
}
}
int query (int v, vector <int> &drzewo){
v += base;
int wynik = drzewo[v];
while (v > 1){
v /= 2;
wynik = max(wynik, drzewo[v]);
}
return wynik;
}
ll NWD(ll a, ll b){
if(b == 0) return a;
return NWD(b, a%b);
}
pair <ll, ll> dodawanie(pair <ll, ll> a, pair <ll, ll> b){
ll mianownik = (a.second*b.second)/NWD(a.second, b.second);
ll licznik = a.first*(mianownik/a.second) + b.first*(mianownik/b.second);
ll dzielnik = NWD(licznik, mianownik);
return {licznik/dzielnik, mianownik/dzielnik};
}
ll szybkie_potegowanie(ll a, ll b, ll mod){
ll wynik = 1;
a = a % mod;
while (b > 0){
if (b % 2 == 1){
wynik = (wynik * a) % mod;
}
a = (a * a) % mod;
b /= 2;
}
return wynik;
}
ll odwrotnosc_modulo(ll a, ll mod){
return szybkie_potegowanie(a, mod-2, mod);
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int n;
cin >> n;
while (base < 2*n){
base *= 2;
}
vector <int> drzewo(2*base, 0);
vector <vector<int>> graf(n+1);
for (int i = 1; i <= n; i++){
int a, b;
cin >> a >> b;
int aq = query(a, drzewo);
int bq = query(b, drzewo);
if (aq != 0){
graf[i].push_back(aq);
}
if (bq != 0){
graf[i].push_back(bq);
}
update(a, b, i, drzewo);
}
//transpozycja grafu
vector <vector<int>> grafT (n+1);
for (int i = 1; i <= n; i++){
for (int j = 0; j < graf[i].size(); j++){
grafT[graf[i][j]].push_back(i);
}
}
vector <int> dostepne(n+1, 0);
for (int i = 1; i <= n; i++){
vector <bool> odwiedzone(n+1, 0);
odwiedzone[i] = 1;
queue <int> kolejka;
kolejka.push(i);
while (!kolejka.empty()){
int v = kolejka.front();
kolejka.pop();
for (int j = 0; j < grafT[v].size(); j++){
if (odwiedzone[grafT[v][j]] == 0){
odwiedzone[grafT[v][j]] = 1;
kolejka.push(grafT[v][j]);
}
}
}
for (int j = 1; j <= n; j++){
if (odwiedzone[j] == 1){
dostepne[i]++;
}
}
}
ll akt_p = 1, akt_q = dostepne[1];
for (int i = 2; i <= n; i++){
pair<long, long> pom = dodawanie({akt_p, akt_q}, {1, dostepne[i]});
akt_p = pom.first; akt_q = pom.second;
}
cout << ((akt_p%1000000007)*odwrotnosc_modulo(akt_q, 1000000007))%1000000007 << "\n";
}
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 | #include <iostream> #include <vector> #include <algorithm> #include <queue> #define ll unsigned long long using namespace std; int base = 1; void update(int l, int r, int x, vector <int> &drzewo){ l += base - 1; r += base + 1; while (l/2 != r/2){ if (l % 2 == 0){ drzewo[l+1] = x; } if (r % 2 == 1){ drzewo[r-1] = x; } l /= 2; r /= 2; } } int query (int v, vector <int> &drzewo){ v += base; int wynik = drzewo[v]; while (v > 1){ v /= 2; wynik = max(wynik, drzewo[v]); } return wynik; } ll NWD(ll a, ll b){ if(b == 0) return a; return NWD(b, a%b); } pair <ll, ll> dodawanie(pair <ll, ll> a, pair <ll, ll> b){ ll mianownik = (a.second*b.second)/NWD(a.second, b.second); ll licznik = a.first*(mianownik/a.second) + b.first*(mianownik/b.second); ll dzielnik = NWD(licznik, mianownik); return {licznik/dzielnik, mianownik/dzielnik}; } ll szybkie_potegowanie(ll a, ll b, ll mod){ ll wynik = 1; a = a % mod; while (b > 0){ if (b % 2 == 1){ wynik = (wynik * a) % mod; } a = (a * a) % mod; b /= 2; } return wynik; } ll odwrotnosc_modulo(ll a, ll mod){ return szybkie_potegowanie(a, mod-2, mod); } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n; cin >> n; while (base < 2*n){ base *= 2; } vector <int> drzewo(2*base, 0); vector <vector<int>> graf(n+1); for (int i = 1; i <= n; i++){ int a, b; cin >> a >> b; int aq = query(a, drzewo); int bq = query(b, drzewo); if (aq != 0){ graf[i].push_back(aq); } if (bq != 0){ graf[i].push_back(bq); } update(a, b, i, drzewo); } //transpozycja grafu vector <vector<int>> grafT (n+1); for (int i = 1; i <= n; i++){ for (int j = 0; j < graf[i].size(); j++){ grafT[graf[i][j]].push_back(i); } } vector <int> dostepne(n+1, 0); for (int i = 1; i <= n; i++){ vector <bool> odwiedzone(n+1, 0); odwiedzone[i] = 1; queue <int> kolejka; kolejka.push(i); while (!kolejka.empty()){ int v = kolejka.front(); kolejka.pop(); for (int j = 0; j < grafT[v].size(); j++){ if (odwiedzone[grafT[v][j]] == 0){ odwiedzone[grafT[v][j]] = 1; kolejka.push(grafT[v][j]); } } } for (int j = 1; j <= n; j++){ if (odwiedzone[j] == 1){ dostepne[i]++; } } } ll akt_p = 1, akt_q = dostepne[1]; for (int i = 2; i <= n; i++){ pair<long, long> pom = dodawanie({akt_p, akt_q}, {1, dostepne[i]}); akt_p = pom.first; akt_q = pom.second; } cout << ((akt_p%1000000007)*odwrotnosc_modulo(akt_q, 1000000007))%1000000007 << "\n"; } |
English