#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <limits>
#include <numeric>
#include <string>
#include <utility>
#include <vector>

using Clause = std::vector<int>;

struct Formula {
    int vars = 0;
    std::vector<Clause> clauses;
};

static bool read_dimacs(const std::string& path, Formula& f) {
    std::ifstream in(path);
    if (!in) return false;
    std::string tok;
    while (in >> tok) {
        if (tok == "c") {
            std::string rest;
            std::getline(in, rest);
        } else if (tok == "p") {
            std::string cnf;
            int m;
            in >> cnf >> f.vars >> m;
            f.clauses.reserve(m);
        } else {
            Clause c;
            int lit = std::stoi(tok);
            while (lit != 0) {
                c.push_back(lit);
                in >> lit;
            }
            if (!c.empty()) f.clauses.push_back(std::move(c));
        }
    }
    return f.vars > 0 && !f.clauses.empty();
}

static int lit_value(int lit, const std::vector<int8_t>& asg) {
    int v = std::abs(lit);
    int8_t a = asg[v];
    if (a == 0) return 0;
    bool val = a > 0;
    if (lit < 0) val = !val;
    return val ? 1 : -1;
}

static bool set_lit(int lit, std::vector<int8_t>& asg) {
    int v = std::abs(lit);
    int8_t val = lit > 0 ? 1 : -1;
    if (asg[v] == -val) return false;
    asg[v] = val;
    return true;
}

static bool unit_propagate(const Formula& f, size_t upto_clause, std::vector<int8_t>& asg) {
    bool changed = true;
    int rounds = 0;
    while (changed) {
        changed = false;
        if (++rounds > f.vars + 5) return false;
        for (size_t ci = 0; ci < upto_clause; ++ci) {
            const Clause& c = f.clauses[ci];
            bool sat = false;
            int unassigned = 0;
            int last = 0;
            for (int lit : c) {
                int lv = lit_value(lit, asg);
                if (lv > 0) {
                    sat = true;
                    break;
                }
                if (lv == 0) {
                    ++unassigned;
                    last = lit;
                }
            }
            if (sat) continue;
            if (unassigned == 0) return false;
            if (unassigned == 1) {
                int v = std::abs(last);
                int8_t before = asg[v];
                if (!set_lit(last, asg)) return false;
                if (asg[v] != before) changed = true;
            }
        }
    }
    return true;
}

static int find_primary_count(const Formula& f) {
    for (const Clause& c : f.clauses) {
        if (c.size() < 20) continue;
        bool ok = true;
        for (size_t i = 0; i < c.size(); ++i) {
            if (c[i] != -static_cast<int>(i + 1)) {
                ok = false;
                break;
            }
        }
        if (ok) return static_cast<int>(c.size());
    }
    return 0;
}

static size_t final_equality_start(const Formula& f, std::vector<std::pair<int,int>>& pairs) {
    size_t idx = f.clauses.size();
    std::vector<std::pair<int,int>> rev;
    while (idx >= 4) {
        const Clause& c1 = f.clauses[idx - 4];
        const Clause& c2 = f.clauses[idx - 3];
        const Clause& c3 = f.clauses[idx - 2];
        const Clause& c4 = f.clauses[idx - 1];
        if (c1.size() != 3 || c2.size() != 3 || c3.size() != 2 || c4.size() != 2) break;
        int a = c1[0], b = c1[1], d = -c1[2];
        if (c2[0] == -a && c2[1] == -b && c2[2] == -d &&
            c3[0] == a && c3[1] == -b &&
            c4[0] == -a && c4[1] == b) {
            rev.push_back({a, b});
            idx -= 4;
        } else {
            break;
        }
    }
    std::reverse(rev.begin(), rev.end());
    pairs = std::move(rev);
    return idx;
}

static bool eval_diff(const Formula& f, size_t gate_clause_end,
                      const std::vector<std::pair<int,int>>& pairs,
                      const std::vector<int>& chosen, long long& diff,
                      std::vector<int8_t>* out_asg = nullptr) {
    std::vector<int8_t> asg(f.vars + 1, 0);
    for (size_t i = 1; i < chosen.size(); ++i) {
        if (!set_lit(chosen[i] ? static_cast<int>(i) : -static_cast<int>(i), asg)) return false;
    }
    if (!unit_propagate(f, gate_clause_end, asg)) return false;
    long long left = 0, right = 0;
    if (pairs.size() >= 62) return false;
    for (size_t i = 0; i < pairs.size(); ++i) {
        int la = lit_value(pairs[i].first, asg);
        int lb = lit_value(pairs[i].second, asg);
        if (la == 0 || lb == 0) return false;
        if (la > 0) left |= (1LL << i);
        if (lb > 0) right |= (1LL << i);
    }
    diff = left - right;
    if (out_asg) *out_asg = std::move(asg);
    return true;
}

static std::vector<std::vector<uint64_t>> build_dp(
        const std::vector<long long>& w, int l, int r, int max_card, long long target) {
    size_t words = static_cast<size_t>(target / 64 + 1);
    std::vector<std::vector<uint64_t>> dp(max_card + 1, std::vector<uint64_t>(words, 0));
    dp[0][0] = 1;
    for (int i = l; i < r; ++i) {
        long long sh = w[i];
        if (sh > target) continue;
        int word_shift = static_cast<int>(sh / 64);
        int bit_shift = static_cast<int>(sh % 64);
        int upto = std::min(max_card, i - l + 1);
        for (int c = upto; c >= 1; --c) {
            const auto& src = dp[c - 1];
            auto& dst = dp[c];
            for (int wi = static_cast<int>(words) - 1 - word_shift; wi >= 0; --wi) {
                uint64_t val = src[wi];
                if (!val) continue;
                size_t pos = static_cast<size_t>(wi + word_shift);
                dst[pos] |= val << bit_shift;
                if (bit_shift && pos + 1 < words) dst[pos + 1] |= val >> (64 - bit_shift);
            }
            int extra = static_cast<int>((words * 64) - (target + 1));
            if (extra > 0) dst.back() &= (~0ULL >> extra);
        }
    }
    return dp;
}

static bool test_bit(const std::vector<uint64_t>& bs, long long s) {
    if (s < 0) return false;
    size_t pos = static_cast<size_t>(s / 64);
    if (pos >= bs.size()) return false;
    return (bs[pos] >> (s % 64)) & 1ULL;
}

static bool reconstruct_dc(const std::vector<long long>& w, int l, int r, int card,
                           long long sum, std::vector<int>& picked) {
    if (card < 0 || sum < 0) return false;
    if (l == r) return card == 0 && sum == 0;
    if (r == l + 1) {
        if (card == 0 && sum == 0) return true;
        if (card == 1 && sum == w[l]) {
            picked[l] = 1;
            return true;
        }
        return false;
    }
    int m = (l + r) / 2;
    int left_n = m - l, right_n = r - m;
    int max_left = std::min(card, left_n);
    int max_right = std::min(card, right_n);
    auto left = build_dp(w, l, m, max_left, sum);
    auto right = build_dp(w, m, r, max_right, sum);
    for (int lc = 0; lc <= max_left; ++lc) {
        int rc = card - lc;
        if (rc < 0 || rc > max_right) continue;
        const auto& lbs = left[lc];
        for (long long s = 0; s <= sum; ++s) {
            if (test_bit(lbs, s) && test_bit(right[rc], sum - s)) {
                return reconstruct_dc(w, l, m, lc, s, picked) &&
                       reconstruct_dc(w, m, r, rc, sum - s, picked);
            }
        }
    }
    return false;
}

static bool solve_partition(const std::vector<long long>& rel, int k, std::vector<int>& picked) {
    int n = static_cast<int>(rel.size());
    long long mn = *std::min_element(rel.begin(), rel.end());
    std::vector<long long> w(n);
    long long total = 0;
    for (int i = 0; i < n; ++i) {
        w[i] = rel[i] - mn;
        total += w[i];
    }
    std::fprintf(stderr, "c recovered normalized total %lld, parity %lld\n", total, total & 1LL);
    if (total & 1LL) return false;
    long long target = total / 2;
    std::fprintf(stderr, "c recovered normalized target %lld, max weight %lld\n",
                 target, *std::max_element(w.begin(), w.end()));
    auto dp = build_dp(w, 0, n, k, target);
    if (!test_bit(dp[k], target)) return false;
    picked.assign(n, 0);
    return reconstruct_dc(w, 0, n, k, target, picked);
}

static bool check_full(const Formula& f, const std::vector<int8_t>& asg) {
    for (const Clause& c : f.clauses) {
        bool sat = false;
        for (int lit : c) {
            if (lit_value(lit, asg) > 0) {
                sat = true;
                break;
            }
        }
        if (!sat) return false;
    }
    return true;
}

struct CdclClause {
    std::vector<int> lits;
    bool learnt = false;
};

struct CdclSolver {
    int vars = 0;
    std::vector<CdclClause> clauses;
    std::vector<std::vector<int>> watches;
    std::vector<int8_t> assigns;
    std::vector<int> levels;
    std::vector<int> reasons;
    std::vector<int> trail;
    std::vector<int> trail_lim;
    std::vector<uint8_t> seen;
    std::vector<int8_t> phase;
    std::vector<double> activity;
    std::vector<std::vector<int>> proof_clauses;
    int qhead = 0;
    double var_inc = 1.0;
    int primary_count = 0;
    long long conflicts_seen = 0;

    explicit CdclSolver(const Formula& f, int primary = 0) : vars(f.vars), watches(2 * f.vars + 2),
        assigns(f.vars + 1, 0), levels(f.vars + 1, 0), reasons(f.vars + 1, -1),
        seen(f.vars + 1, 0), phase(f.vars + 1, -1), activity(f.vars + 1, 0.0),
        primary_count(primary) {
        clauses.reserve(f.clauses.size() + 10000);
        for (const Clause& c : f.clauses) {
            clauses.push_back({c, false});
            for (int lit : c) activity[std::abs(lit)] += 1.0;
        }
        for (int v = 1; v <= primary_count && v <= vars; ++v) activity[v] += 1000000.0;
    }

    static int lit_index(int lit) {
        int v = std::abs(lit) - 1;
        return lit > 0 ? 2 * v : 2 * v + 1;
    }

    int lit_value(int lit) const {
        int8_t a = assigns[std::abs(lit)];
        if (a == 0) return 0;
        bool val = a > 0;
        if (lit < 0) val = !val;
        return val ? 1 : -1;
    }

    int decision_level() const {
        return static_cast<int>(trail_lim.size());
    }

    bool enqueue(int lit, int reason) {
        int v = std::abs(lit);
        int8_t val = lit > 0 ? 1 : -1;
        if (assigns[v] != 0) return assigns[v] == val;
        assigns[v] = val;
        phase[v] = val;
        levels[v] = decision_level();
        reasons[v] = reason;
        trail.push_back(lit);
        return true;
    }

    bool attach_initial() {
        for (int ci = 0; ci < static_cast<int>(clauses.size()); ++ci) {
            auto& c = clauses[ci].lits;
            if (c.empty()) return false;
            if (c.size() == 1) {
                if (!enqueue(c[0], ci)) return false;
            } else {
                watches[lit_index(c[0])].push_back(ci);
                watches[lit_index(c[1])].push_back(ci);
            }
        }
        return true;
    }

    void attach_clause(int ci) {
        auto& c = clauses[ci].lits;
        if (c.size() >= 2) {
            watches[lit_index(c[0])].push_back(ci);
            watches[lit_index(c[1])].push_back(ci);
        }
    }

    int propagate() {
        while (qhead < static_cast<int>(trail.size())) {
            int p = trail[qhead++];
            auto& ws = watches[lit_index(-p)];
            int out = 0;
            for (int in = 0; in < static_cast<int>(ws.size()); ++in) {
                int ci = ws[in];
                auto& c = clauses[ci].lits;
                if (c.size() == 1) {
                    ws[out++] = ci;
                    if (lit_value(c[0]) < 0) {
                        while (in + 1 < static_cast<int>(ws.size())) ws[out++] = ws[++in];
                        ws.resize(out);
                        return ci;
                    }
                    continue;
                }
                if (c[0] != -p) std::swap(c[0], c[1]);
                if (lit_value(c[1]) > 0) {
                    ws[out++] = ci;
                    continue;
                }
                bool moved = false;
                for (int k = 2; k < static_cast<int>(c.size()); ++k) {
                    if (lit_value(c[k]) >= 0) {
                        std::swap(c[0], c[k]);
                        watches[lit_index(c[0])].push_back(ci);
                        moved = true;
                        break;
                    }
                }
                if (moved) continue;
                ws[out++] = ci;
                if (lit_value(c[1]) < 0) {
                    while (in + 1 < static_cast<int>(ws.size())) ws[out++] = ws[++in];
                    ws.resize(out);
                    return ci;
                }
                if (!enqueue(c[1], ci)) {
                    while (in + 1 < static_cast<int>(ws.size())) ws[out++] = ws[++in];
                    ws.resize(out);
                    return ci;
                }
            }
            ws.resize(out);
        }
        return -1;
    }

    void cancel_until(int level) {
        if (decision_level() <= level) return;
        int keep = level == 0 ? 0 : trail_lim[level];
        for (int i = static_cast<int>(trail.size()) - 1; i >= keep; --i) {
            int v = std::abs(trail[i]);
            assigns[v] = 0;
            levels[v] = 0;
            reasons[v] = -1;
        }
        trail.resize(keep);
        trail_lim.resize(level);
        qhead = keep;
    }

    void bump_clause_vars(const std::vector<int>& c) {
        for (int lit : c) activity[std::abs(lit)] += var_inc;
        var_inc *= 1.05;
        if (var_inc > 1e100) {
            for (int v = 1; v <= vars; ++v) activity[v] *= 1e-100;
            var_inc *= 1e-100;
        }
    }

    void analyze(int confl, std::vector<int>& learnt, int& backtrack) {
        learnt.clear();
        learnt.push_back(0);
        int path_c = 0;
        int p = 0;
        int skip_var = 0;
        int idx = static_cast<int>(trail.size()) - 1;
        int ci = confl;
        do {
            const auto& c = clauses[ci].lits;
            for (int lit : c) {
                int v = std::abs(lit);
                if (v == skip_var) continue;
                if (!seen[v] && levels[v] > 0) {
                    seen[v] = 1;
                    if (levels[v] == decision_level()) {
                        ++path_c;
                    } else {
                        learnt.push_back(lit);
                    }
                }
            }
            while (idx >= 0 && !seen[std::abs(trail[idx])]) --idx;
            p = trail[idx--];
            seen[std::abs(p)] = 0;
            --path_c;
            if (path_c > 0) {
                skip_var = std::abs(p);
                ci = reasons[skip_var];
            }
        } while (path_c > 0);
        learnt[0] = -p;
        backtrack = 0;
        for (int i = 1; i < static_cast<int>(learnt.size()); ++i) {
            backtrack = std::max(backtrack, levels[std::abs(learnt[i])]);
        }
        for (int lit : learnt) seen[std::abs(lit)] = 0;
        bump_clause_vars(learnt);
    }

    int pick_branch_lit() const {
        int best = 0;
        double best_act = -1.0;
        for (int v = 1; v <= vars; ++v) {
            if (assigns[v] == 0 && activity[v] > best_act) {
                best_act = activity[v];
                best = v;
            }
        }
        if (best == 0) return 0;
        return phase[best] > 0 ? best : -best;
    }

    bool solve_unsat(long long conflict_limit) {
        if (!attach_initial()) {
            proof_clauses.push_back({});
            return true;
        }
        int confl = propagate();
        if (confl != -1) {
            proof_clauses.push_back({});
            return true;
        }
        long long conflicts = 0;
        long long restart_at = 100;
        long long conflicts_since_restart = 0;
        int pending_conflict = -1;
        std::vector<int> learnt;
        while (true) {
            if (pending_conflict != -1) {
                confl = pending_conflict;
                pending_conflict = -1;
            } else {
                confl = propagate();
            }
            if (confl != -1) {
                if (decision_level() == 0) {
                    proof_clauses.push_back({});
                    return true;
                }
                conflicts_seen = ++conflicts;
                if (conflicts > conflict_limit) return false;
                ++conflicts_since_restart;
                int bt = 0;
                analyze(confl, learnt, bt);
                cancel_until(bt);
                int ci = static_cast<int>(clauses.size());
                clauses.push_back({learnt, true});
                proof_clauses.push_back(learnt);
                if (learnt.size() == 1) {
                    if (!enqueue(learnt[0], ci)) {
                        pending_conflict = ci;
                        continue;
                    }
                } else {
                    attach_clause(ci);
                    if (!enqueue(learnt[0], ci)) {
                        pending_conflict = ci;
                        continue;
                    }
                }
                if (conflicts_since_restart >= restart_at) {
                    cancel_until(0);
                    conflicts_since_restart = 0;
                    restart_at = std::min<long long>(restart_at + restart_at / 2 + 1, 20000);
                }
            } else {
                int next = pick_branch_lit();
                if (next == 0) return false;
                trail_lim.push_back(static_cast<int>(trail.size()));
                if (!enqueue(next, -1)) return false;
            }
        }
    }
};

static void write_pbp_clause(std::ofstream& out, const std::vector<int>& clause) {
    out << "rup";
    for (int lit : clause) {
        out << " 1 ";
        if (lit < 0) out << "~";
        out << "x" << std::abs(lit);
    }
    out << " >= 1 ;\n";
}

static bool run_cdcl_proof(const Formula& f, const std::string& proof_path,
                           long long default_limit, int default_primary,
                           const char* label) {
    std::remove(proof_path.c_str());
    long long limit = default_limit;
    if (const char* env = std::getenv("MCP_CDCL_LIMIT")) {
        char* end = nullptr;
        long long parsed = std::strtoll(env, &end, 10);
        if (end && *end == '\0' && parsed > 0) limit = parsed;
    }
    int primary = default_primary;
    if (const char* env = std::getenv("MCP_CDCL_PRIMARY")) {
        char* end = nullptr;
        long long parsed = std::strtoll(env, &end, 10);
        if (end && *end == '\0' && parsed > 0 && parsed <= f.vars) primary = static_cast<int>(parsed);
    }
    CdclSolver s(f, primary);
    if (!s.solve_unsat(limit)) {
        std::fprintf(stderr, "c %s cdcl stopped after %lld conflicts (limit %lld, clauses %zu)\n",
                     label, s.conflicts_seen, limit, f.clauses.size());
        return false;
    }
    std::fprintf(stderr, "c %s cdcl proved unsat after %lld conflicts, proof clauses %zu, clauses %zu\n",
                 label, s.conflicts_seen, s.proof_clauses.size(), f.clauses.size());
    std::ofstream out(proof_path);
    if (!out) return false;
    out << "pseudo-Boolean proof version 3.0\n";
    for (const auto& c : s.proof_clauses) write_pbp_clause(out, c);
    out << "output NONE ;\n";
    out << "conclusion UNSAT : -1 ;\n";
    out << "end pseudo-Boolean proof ;\n";
    return true;
}

static Formula lowbit_cone_formula(const Formula& f, size_t eq_start,
                                   const std::vector<std::pair<int,int>>& pairs,
                                   int primary_count) {
    Formula sub;
    sub.vars = f.vars;
    if (pairs.empty() || eq_start + 4 > f.clauses.size()) return sub;

    std::vector<std::vector<int>> by_max(f.vars + 1);
    for (size_t ci = 0; ci < eq_start; ++ci) {
        int mx = 0;
        for (int lit : f.clauses[ci]) mx = std::max(mx, std::abs(lit));
        if (mx > primary_count && mx <= f.vars) by_max[mx].push_back(static_cast<int>(ci));
    }

    std::vector<uint8_t> need(f.vars + 1, 0), used(f.clauses.size(), 0);
    std::vector<int> stack;
    auto add_var = [&](int v) {
        v = std::abs(v);
        if (v >= 1 && v <= f.vars && !need[v]) {
            need[v] = 1;
            stack.push_back(v);
        }
    };
    for (size_t ci = eq_start; ci < eq_start + 4; ++ci) {
        used[ci] = 1;
        for (int lit : f.clauses[ci]) add_var(lit);
    }
    while (!stack.empty()) {
        int v = stack.back();
        stack.pop_back();
        if (v <= primary_count) continue;
        for (int ci : by_max[v]) {
            if (used[ci]) continue;
            used[ci] = 1;
            for (int lit : f.clauses[ci]) add_var(lit);
        }
    }

    sub.clauses.reserve(f.clauses.size() / 8);
    for (size_t ci = 0; ci < f.clauses.size(); ++ci) {
        if (used[ci]) sub.clauses.push_back(f.clauses[ci]);
    }
    return sub;
}

static bool prove_unsat_lowbit_cone(const Formula& f, size_t eq_start,
                                    const std::vector<std::pair<int,int>>& pairs,
                                    int primary_count,
                                    const std::string& proof_path) {
    Formula cone = lowbit_cone_formula(f, eq_start, pairs, primary_count);
    if (cone.clauses.empty()) return false;
    std::fprintf(stderr, "c low-bit cone clauses %zu of %zu\n", cone.clauses.size(), f.clauses.size());
    return run_cdcl_proof(cone, proof_path, 1000000, 0, "low-bit cone");
}

static bool prove_unsat_cdcl(const Formula& f, const std::string& proof_path) {
    return run_cdcl_proof(f, proof_path, 300000, 0, "full");
}

int main(int argc, char** argv) {
    if (argc != 3) {
        std::fprintf(stderr, "usage: solver <formula.cnf> <out.pbp>\n");
        return 1;
    }
    Formula f;
    if (!read_dimacs(argv[1], f)) {
        std::printf("s UNKNOWN\n");
        return 0;
    }
    std::vector<std::pair<int,int>> pairs;
    size_t eq_start = final_equality_start(f, pairs);
    int n = find_primary_count(f);
    if (n <= 0 || (n % 2) || pairs.size() < 8 || pairs.size() > 60) {
        std::printf("c unsupported structure n=%d final_bits=%zu\n", n, pairs.size());
        std::printf("s UNKNOWN\n");
        return 0;
    }
    int k = n / 2;
    std::printf("c detected balanced PEQNP partition n=%d final_bits=%zu\n", n, pairs.size());

    std::vector<int> base(n + 1, 0);
    for (int i = 1; i <= k; ++i) base[i] = 1;
    long long dbase = 0;
    if (!eval_diff(f, eq_start, pairs, base, dbase)) {
        std::printf("c failed to evaluate base circuit\ns UNKNOWN\n");
        return 0;
    }
    int anchor = k + 1;
    int pivot = 1;
    std::vector<long long> rel(n, 0);
    for (int i = 1; i <= k; ++i) {
        std::vector<int> cur = base;
        cur[i] = 0;
        cur[anchor] = 1;
        long long d = 0;
        if (!eval_diff(f, eq_start, pairs, cur, d) || ((d - dbase) & 1LL)) {
            std::printf("c failed to recover selected weight %d\ns UNKNOWN\n", i);
            return 0;
        }
        rel[i - 1] = -((d - dbase) / 2);
    }
    for (int j = k + 1; j <= n; ++j) {
        std::vector<int> cur = base;
        cur[pivot] = 0;
        cur[j] = 1;
        long long d = 0;
        if (!eval_diff(f, eq_start, pairs, cur, d) || ((d - dbase) & 1LL)) {
            std::printf("c failed to recover unselected weight %d\ns UNKNOWN\n", j);
            return 0;
        }
        rel[j - 1] = rel[pivot - 1] + ((d - dbase) / 2);
    }

    std::vector<int> picked0;
    if (!solve_partition(rel, k, picked0)) {
        std::printf("c high-level DP found no balanced equal-sum partition; trying low-bit cone RUP proof\n");
        if (prove_unsat_lowbit_cone(f, eq_start, pairs, n, argv[2])) {
            std::printf("s UNSATISFIABLE\n");
            return 20;
        }
        std::printf("c low-bit cone proof failed; trying full CDCL RUP proof\n");
        if (prove_unsat_cdcl(f, argv[2])) {
            std::printf("s UNSATISFIABLE\n");
            return 20;
        }
        std::printf("c CDCL proof search did not finish within internal limit\ns UNKNOWN\n");
        return 0;
    }
    std::vector<int> chosen(n + 1, 0);
    for (int i = 1; i <= n; ++i) chosen[i] = picked0[i - 1];
    long long dfinal = 1;
    std::vector<int8_t> asg;
    if (!eval_diff(f, f.clauses.size(), pairs, chosen, dfinal, &asg) || dfinal != 0) {
        std::printf("c candidate failed full propagation diff=%lld\ns UNKNOWN\n", dfinal);
        return 0;
    }
    for (int v = 1; v <= f.vars; ++v) {
        if (asg[v] == 0) asg[v] = -1;
    }
    if (!check_full(f, asg)) {
        std::printf("c candidate failed independent CNF check\ns UNKNOWN\n");
        return 0;
    }
    std::printf("s SATISFIABLE\n");
    std::printf("v");
    for (int v = 1; v <= f.vars; ++v) {
        std::printf(" %d", asg[v] > 0 ? v : -v);
        if (v % 100 == 0) std::printf("\nv");
    }
    std::printf(" 0\n");
    return 10;
}
