#include <algorithm> #include <cstdlib> #include <iostream> #include <sstream> #include <string> #include <tuple> #include <utility> #include <vector> using namespace std; namespace { int const mod = 1000000007; struct Clause { int first; int last; vector<bool> pos; explicit Clause(vector<int> const& v) { auto e = minmax_element(v.begin(), v.end(), [](int a, int b) { return abs(a) < abs(b); }); first = abs(*e.first); last = abs(*e.second); pos.resize(last - first + 1); for (int x: v) { pos[abs(x) - first] = (x > 0); } } bool operator[](int x) const { return pos[x - first]; } }; using Formula = vector<Clause>; Formula parse(string const& s) { istringstream str{s}; Formula res; while (true) { char c; str >> c; vector<int> clause; while (true) { str >> c; int sign; if (c == '~') { sign = -1; str >> c; } else { sign = 1; } int i; str >> i; clause.emplace_back(sign * i); str >> c; if (c == ')') break; } res.emplace_back(clause); str >> c; if (!str) break; } return res; } struct Node { int next[2]; Node(): next{-1, -1} { } }; vector<Node> build_bdd(int n, Formula const& formula) { vector<Node> nodes; auto new_node = [&]() -> int { nodes.emplace_back(); return nodes.size() - 1; }; vector<vector<int>> by_first(n + 1); for (int i = 0; i < int(formula.size()); ++i) { by_first[formula[i].first].emplace_back(i); } vector<tuple<int, int, vector<int>>> active; active.emplace_back(new_node(), -1, move(by_first[1])); for (int v = 1; v <= n; ++v) { decltype (active) new_active; int orphan = 0; if (v < n) { orphan = new_node(); new_active.emplace_back(orphan, -1, move(by_first[v + 1])); } for (auto a: active) { int node = get<0>(a); int prev = get<1>(a); if (prev < 0) prev = get<0>(active[0]); vector<int> const& clauses = get<2>(a); bool bad[2] = {}; vector<int> split[2]; for (auto c: clauses) { int b = !formula[c][v]; if (formula[c].last == v) bad[b] = true; if (bad[b]) continue; split[b].emplace_back(c); } for (int b = 0; b < 2; ++b) { int new_prev = -1; if (!bad[b] && prev != node && nodes[prev].next[b] != orphan) { new_prev = nodes[prev].next[b]; if (new_prev < 0) bad[b] = true; } int next; if (bad[b]) next = -1; else if (split[b].empty()) { if (prev == node) next = orphan; else next = nodes[prev].next[b]; } else { next = new_node(); new_active.emplace_back(next, new_prev, move(split[b])); } nodes[node].next[b] = next; // clog << "Ustawiliśmy " << node << " " << ("FT"[b]) << " na " << next << (next == orphan ? " [O]" : "") << endl; } } active = move(new_active); } return nodes; } int count_bdd(vector<Node> const& bdd) { int m = bdd.size(); vector<int> res(m); for (int i = m-1; i >= 0; --i) { for (int b = 0; b < 2; ++b) { int next = bdd[i].next[b]; if (next == 0) { ++res[i]; } else if (next > 0) { res[i] += res[next]; } } if (res[i] >= mod) res[i] -= mod; } return res[0]; } int solve(int n, Formula const& formula) { return count_bdd(build_bdd(n, formula)); } } int main() { iostream::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; string s; getline(cin >> ws, s); cout << solve(n, parse(s)) << endl; 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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | #include <algorithm> #include <cstdlib> #include <iostream> #include <sstream> #include <string> #include <tuple> #include <utility> #include <vector> using namespace std; namespace { int const mod = 1000000007; struct Clause { int first; int last; vector<bool> pos; explicit Clause(vector<int> const& v) { auto e = minmax_element(v.begin(), v.end(), [](int a, int b) { return abs(a) < abs(b); }); first = abs(*e.first); last = abs(*e.second); pos.resize(last - first + 1); for (int x: v) { pos[abs(x) - first] = (x > 0); } } bool operator[](int x) const { return pos[x - first]; } }; using Formula = vector<Clause>; Formula parse(string const& s) { istringstream str{s}; Formula res; while (true) { char c; str >> c; vector<int> clause; while (true) { str >> c; int sign; if (c == '~') { sign = -1; str >> c; } else { sign = 1; } int i; str >> i; clause.emplace_back(sign * i); str >> c; if (c == ')') break; } res.emplace_back(clause); str >> c; if (!str) break; } return res; } struct Node { int next[2]; Node(): next{-1, -1} { } }; vector<Node> build_bdd(int n, Formula const& formula) { vector<Node> nodes; auto new_node = [&]() -> int { nodes.emplace_back(); return nodes.size() - 1; }; vector<vector<int>> by_first(n + 1); for (int i = 0; i < int(formula.size()); ++i) { by_first[formula[i].first].emplace_back(i); } vector<tuple<int, int, vector<int>>> active; active.emplace_back(new_node(), -1, move(by_first[1])); for (int v = 1; v <= n; ++v) { decltype (active) new_active; int orphan = 0; if (v < n) { orphan = new_node(); new_active.emplace_back(orphan, -1, move(by_first[v + 1])); } for (auto a: active) { int node = get<0>(a); int prev = get<1>(a); if (prev < 0) prev = get<0>(active[0]); vector<int> const& clauses = get<2>(a); bool bad[2] = {}; vector<int> split[2]; for (auto c: clauses) { int b = !formula[c][v]; if (formula[c].last == v) bad[b] = true; if (bad[b]) continue; split[b].emplace_back(c); } for (int b = 0; b < 2; ++b) { int new_prev = -1; if (!bad[b] && prev != node && nodes[prev].next[b] != orphan) { new_prev = nodes[prev].next[b]; if (new_prev < 0) bad[b] = true; } int next; if (bad[b]) next = -1; else if (split[b].empty()) { if (prev == node) next = orphan; else next = nodes[prev].next[b]; } else { next = new_node(); new_active.emplace_back(next, new_prev, move(split[b])); } nodes[node].next[b] = next; // clog << "Ustawiliśmy " << node << " " << ("FT"[b]) << " na " << next << (next == orphan ? " [O]" : "") << endl; } } active = move(new_active); } return nodes; } int count_bdd(vector<Node> const& bdd) { int m = bdd.size(); vector<int> res(m); for (int i = m-1; i >= 0; --i) { for (int b = 0; b < 2; ++b) { int next = bdd[i].next[b]; if (next == 0) { ++res[i]; } else if (next > 0) { res[i] += res[next]; } } if (res[i] >= mod) res[i] -= mod; } return res[0]; } int solve(int n, Formula const& formula) { return count_bdd(build_bdd(n, formula)); } } int main() { iostream::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; string s; getline(cin >> ws, s); cout << solve(n, parse(s)) << endl; return 0; } |