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

using std::uint64_t;
using U128 = unsigned __int128;

struct Clause {
    std::vector<int> lits;
};

struct XorEq {
    std::vector<int> vars;
    int rhs = 0;
};

struct LinRow {
    std::vector<uint64_t> w;
    int rhs = 0;
};

static bool get_bit(const std::vector<uint64_t>& w, int v) {
    --v;
    return (w[v >> 6] >> (v & 63)) & 1ULL;
}

static void flip_bit(std::vector<uint64_t>& w, int v) {
    --v;
    w[v >> 6] ^= 1ULL << (v & 63);
}

static void xor_row(LinRow& a, const LinRow& b) {
    for (size_t i = 0; i < a.w.size(); ++i) a.w[i] ^= b.w[i];
    a.rhs ^= b.rhs;
}

static int highest_set_range(const std::vector<uint64_t>& w, int lo, int hi) {
    for (int word = (hi - 1) >> 6; word >= 0; --word) {
        uint64_t x = w[word];
        int word_lo = word << 6;
        int word_hi = word_lo + 63;
        if (word_hi < lo) return 0;
        if (word_hi >= hi) x &= ((hi & 63) == 0 ? ~0ULL : ((1ULL << (hi & 63)) - 1ULL));
        if (word_lo < lo) {
            int clear = lo - word_lo - 1;
            if (clear >= 64) x = 0;
            else if (clear > 0) x &= ~((1ULL << clear) - 1ULL);
        }
        if (x) return word_lo + 64 - __builtin_clzll(x);
    }
    return 0;
}

static int choose_pivot(const LinRow& r, int primary_n, int vars) {
    int p = highest_set_range(r.w, primary_n + 1, vars);
    if (p) return p;
    return highest_set_range(r.w, 1, vars);
}

static bool parse_dimacs(const char* path, int& nvars, std::vector<Clause>& clauses) {
    std::ifstream in(path);
    if (!in) return false;
    std::string tok;
    int declared_clauses = 0;
    while (in >> tok) {
        if (tok == "c") {
            std::string rest;
            std::getline(in, rest);
        } else if (tok == "p") {
            std::string cnf;
            in >> cnf >> nvars >> declared_clauses;
        } else {
            Clause c;
            int lit = std::stoi(tok);
            while (lit != 0) {
                c.lits.push_back(lit);
                in >> lit;
            }
            clauses.push_back(std::move(c));
        }
    }
    return nvars > 0 && !clauses.empty();
}

static bool xor_group(const std::vector<Clause>& clauses, int pos, int arity, XorEq& out) {
    int gsz = 1 << (arity - 1);
    if (pos + gsz > (int)clauses.size()) return false;
    std::vector<int> vars;
    for (const Clause& c : std::vector<Clause>(clauses.begin() + pos, clauses.begin() + pos + gsz)) {
        if ((int)c.lits.size() != arity) return false;
        for (int lit : c.lits) {
            int v = std::abs(lit);
            if (std::find(vars.begin(), vars.end(), v) == vars.end()) vars.push_back(v);
        }
    }
    if ((int)vars.size() != arity) return false;
    std::sort(vars.begin(), vars.end());
    std::vector<unsigned> seen;
    int forbidden_parity = -1;
    for (int i = 0; i < gsz; ++i) {
        const Clause& c = clauses[pos + i];
        std::vector<int> present;
        for (int lit : c.lits) present.push_back(std::abs(lit));
        std::sort(present.begin(), present.end());
        if (present != vars) return false;
        unsigned bits = 0;
        int parity = 0;
        for (int j = 0; j < arity; ++j) {
            int lit_for_v = 0;
            for (int lit : c.lits) {
                if (std::abs(lit) == vars[j]) {
                    lit_for_v = lit;
                    break;
                }
            }
            int bit = lit_for_v < 0 ? 1 : 0;
            bits |= unsigned(bit) << j;
            parity ^= bit;
        }
        if (forbidden_parity < 0) forbidden_parity = parity;
        if (forbidden_parity != parity) return false;
        seen.push_back(bits);
    }
    std::sort(seen.begin(), seen.end());
    if (std::unique(seen.begin(), seen.end()) != seen.end()) return false;
    out.vars = vars;
    out.rhs = 1 ^ forbidden_parity;
    return true;
}

static int parse_xor_prefix(const std::vector<Clause>& clauses, std::vector<XorEq>& eqs) {
    int pos = 0;
    while (pos < (int)clauses.size()) {
        bool ok = false;
        for (int arity : {4, 3, 2, 1}) {
            XorEq e;
            if (xor_group(clauses, pos, arity, e)) {
                eqs.push_back(std::move(e));
                pos += 1 << (arity - 1);
                ok = true;
                break;
            }
        }
        if (!ok) break;
    }
    return pos;
}

static bool unit_propagate(const std::vector<Clause>& clauses, std::vector<int8_t>& asg) {
    bool changed = true;
    while (changed) {
        changed = false;
        for (const Clause& c : clauses) {
            bool sat = false;
            int un = 0, last = 0;
            for (int lit : c.lits) {
                int8_t v = asg[std::abs(lit)];
                if (v < 0) {
                    ++un;
                    last = lit;
                } else if ((v == 1) == (lit > 0)) {
                    sat = true;
                    break;
                }
            }
            if (sat) continue;
            if (un == 0) return false;
            if (un == 1) {
                int var = std::abs(last);
                int8_t val = last > 0 ? 1 : 0;
                if (asg[var] >= 0 && asg[var] != val) return false;
                if (asg[var] < 0) {
                    asg[var] = val;
                    changed = true;
                }
            }
        }
    }
    return true;
}

static bool validate(const std::vector<Clause>& clauses, const std::vector<int8_t>& asg) {
    for (const Clause& c : clauses) {
        bool sat = false;
        for (int lit : c.lits) {
            int8_t v = asg[std::abs(lit)];
            if (v >= 0 && ((v == 1) == (lit > 0))) {
                sat = true;
                break;
            }
        }
        if (!sat) return false;
    }
    return true;
}

static bool finish_assignment(const std::vector<Clause>& clauses, std::vector<int8_t>& asg) {
    if (!unit_propagate(clauses, asg)) return false;
    while (true) {
        int best = 0;
        for (int i = 1; i < (int)asg.size(); ++i) {
            if (asg[i] < 0) {
                best = i;
                break;
            }
        }
        if (!best) return validate(clauses, asg);
        std::vector<int8_t> trial = asg;
        trial[best] = 0;
        if (unit_propagate(clauses, trial)) {
            asg.swap(trial);
            continue;
        }
        asg[best] = 1;
        if (!unit_propagate(clauses, asg)) return false;
    }
}

static bool suffix_accepts_count(int nvars, const std::vector<Clause>& suffix, int first_score, int m, int count) {
    std::vector<int8_t> asg(nvars + 1, -1);
    for (int i = 0; i < m; ++i) asg[first_score + i] = (i < count) ? 1 : 0;
    return unit_propagate(suffix, asg);
}

static void enumerate_supports(const std::vector<uint64_t>& syn, int start, int len, int limit,
                               const std::vector<int>& ids,
                               int idx, int chosen, uint64_t cur_syn, U128 cur_mask,
                               std::vector<std::pair<uint64_t, std::pair<int, U128>>>& out) {
    if (chosen > limit) return;
    if (idx == len) {
        out.push_back({cur_syn, {chosen, cur_mask}});
        return;
    }
    if (chosen + (len - idx) < 0) return;
    enumerate_supports(syn, start, len, limit, ids, idx + 1, chosen, cur_syn, cur_mask, out);
    int pos = ids[start + idx];
    enumerate_supports(syn, start, len, limit, ids, idx + 1, chosen + 1,
                       cur_syn ^ syn[start + idx], cur_mask | (U128(1) << pos), out);
}

static bool find_error_once(uint64_t target, const std::vector<uint64_t>& syn, const std::vector<int>& ids,
                            int m, int t, U128& err) {
    int left_len = m / 2;
    int right_len = m - left_len;
    int small = t / 2;
    int big = std::min(t, small + 2);
    auto try_orientation = [&](int llim, int rlim) -> bool {
        std::vector<std::pair<uint64_t, std::pair<int, U128>>> right;
        enumerate_supports(syn, left_len, right_len, rlim, ids, 0, 0, 0, 0, right);
        std::unordered_map<uint64_t, std::pair<int, U128>> best;
        best.reserve(right.size() * 2 + 1);
        for (auto& e : right) {
            auto it = best.find(e.first);
            if (it == best.end() || e.second.first < it->second.first) best[e.first] = e.second;
        }
        std::vector<std::pair<uint64_t, std::pair<int, U128>>> left;
        enumerate_supports(syn, 0, left_len, llim, ids, 0, 0, 0, 0, left);
        for (auto& e : left) {
            auto it = best.find(target ^ e.first);
            if (it != best.end() && e.second.first + it->second.first <= t) {
                err = e.second.second | it->second.second;
                return true;
            }
        }
        return false;
    };
    if (try_orientation(small, big)) return true;
    if (small != big && try_orientation(big, small)) return true;
    return false;
}

static bool find_error(uint64_t target, const std::vector<uint64_t>& pos_syn, int m, int t, U128& err) {
    std::vector<int> ids(m);
    std::iota(ids.begin(), ids.end(), 0);
    std::vector<uint64_t> syn = pos_syn;
    if (find_error_once(target, syn, ids, m, t, err)) return true;
    uint64_t state = 0x9e3779b97f4a7c15ULL ^ (uint64_t(m) << 32) ^ uint64_t(t);
    for (int attempt = 0; attempt < 4; ++attempt) {
        ids.resize(m);
        std::iota(ids.begin(), ids.end(), 0);
        for (int i = m - 1; i > 0; --i) {
            state = state * 6364136223846793005ULL + 1442695040888963407ULL;
            int j = int(state % uint64_t(i + 1));
            std::swap(ids[i], ids[j]);
        }
        for (int i = 0; i < m; ++i) syn[i] = pos_syn[ids[i]];
        if (find_error_once(target, syn, ids, m, t, err)) return true;
    }
    return false;
}

int main(int argc, char** argv) {
    if (argc != 3) return 1;
    int nvars = 0;
    std::vector<Clause> clauses;
    if (!parse_dimacs(argv[1], nvars, clauses)) return 1;

    std::vector<XorEq> eqs;
    int prefix_end = parse_xor_prefix(clauses, eqs);
    bool debug = std::getenv("LYDEBUG") != nullptr;
    auto unknown = [&](const char* why) {
        if (debug) std::fprintf(stderr, "UNKNOWN: %s\n", why);
        std::cout << "s UNKNOWN\n";
    };
    if (eqs.empty() || prefix_end >= (int)clauses.size()) {
        unknown("no_xor_prefix");
        return 0;
    }

    const Clause& a = clauses[prefix_end];
    const Clause& b = clauses[prefix_end + 1];
    if (a.lits.size() != 2 || b.lits.size() != 2) {
        unknown("bad_suffix_start");
        return 0;
    }
    int common = 0, in1 = 0, in2 = 0;
    for (int x : a.lits) for (int y : b.lits) if (std::abs(x) == std::abs(y)) common = std::abs(x);
    for (int x : a.lits) if (std::abs(x) != common) in1 = std::abs(x);
    for (int y : b.lits) if (std::abs(y) != common) in2 = std::abs(y);
    int primary_n = std::min(in1, in2) - 1;
    if (primary_n < 4 || primary_n > 62) {
        unknown("bad_primary_n");
        return 0;
    }
    int first_score = primary_n + 1;
    int score_m = 2 * primary_n;
    if (first_score + score_m - 1 > nvars) {
        unknown("bad_score_range");
        return 0;
    }

    std::vector<Clause> suffix(clauses.begin() + prefix_end, clauses.end());
    int threshold = -1;
    for (int c = 0; c <= score_m; ++c) {
        if (suffix_accepts_count(nvars, suffix, first_score, score_m, c)) threshold = c;
        else if (threshold >= 0) break;
    }
    if (threshold < 0 || threshold > 12) {
        unknown("bad_threshold");
        return 0;
    }
    if (debug) std::fprintf(stderr, "prefix=%d eqs=%zu N=%d M=%d T=%d\n", prefix_end, eqs.size(), primary_n, score_m, threshold);

    int words = (nvars + 63) >> 6;
    std::vector<LinRow> basis(nvars + 1);
    std::vector<char> has(nvars + 1, 0);
    for (const XorEq& e : eqs) {
        LinRow r;
        r.w.assign(words, 0);
        r.rhs = e.rhs;
        for (int v : e.vars) flip_bit(r.w, v);
        while (true) {
            int p = choose_pivot(r, primary_n, nvars);
            if (!p) {
                if (r.rhs) {
                    unknown("inconsistent_xor_prefix");
                    return 0;
                }
                break;
            }
            if (has[p]) xor_row(r, basis[p]);
            else {
                basis[p] = std::move(r);
                has[p] = 1;
                break;
            }
        }
    }

    std::vector<uint64_t> score_rows(score_m, 0);
    std::vector<int> score_const(score_m, 0);
    for (int i = 0; i < score_m; ++i) {
        int v = first_score + i;
        if (!has[v]) {
            unknown("score_missing_pivot");
            return 0;
        }
        LinRow r = basis[v];
        flip_bit(r.w, v);
        while (true) {
            int p = highest_set_range(r.w, primary_n + 1, nvars);
            if (!p) break;
            if (!has[p]) {
                unknown("score_unreduced_nonprimary");
                return 0;
            }
            xor_row(r, basis[p]);
        }
        uint64_t mask = 0;
        for (int j = 1; j <= primary_n; ++j) if (get_bit(r.w, j)) mask |= 1ULL << (j - 1);
        score_rows[i] = mask;
        score_const[i] = r.rhs;
    }

    std::vector<uint64_t> dep_basis(primary_n + 1, 0);
    std::vector<U128> dep_comb(primary_n + 1, 0);
    std::vector<char> dep_has(primary_n + 1, 0);
    std::vector<U128> nulls;
    for (int i = 0; i < score_m; ++i) {
        uint64_t row = score_rows[i];
        U128 comb = U128(1) << i;
        while (row) {
            int p = 64 - __builtin_clzll(row);
            if (dep_has[p]) {
                row ^= dep_basis[p];
                comb ^= dep_comb[p];
            } else {
                dep_basis[p] = row;
                dep_comb[p] = comb;
                dep_has[p] = 1;
                break;
            }
        }
        if (!row) nulls.push_back(comb);
    }
    if ((int)nulls.size() > 62) {
        unknown("too_many_nulls");
        return 0;
    }
    std::vector<uint64_t> pos_syn(score_m, 0);
    uint64_t target_syn = 0;
    for (int j = 0; j < (int)nulls.size(); ++j) {
        U128 h = nulls[j];
        int pc = 0;
        for (int i = 0; i < score_m; ++i) {
            if ((h >> i) & U128(1)) {
                pos_syn[i] |= 1ULL << j;
                pc ^= score_const[i];
            }
        }
        if (pc) target_syn |= 1ULL << j;
    }

    U128 err = 0;
    if (!find_error(target_syn, pos_syn, score_m, threshold, err)) {
        unknown("no_low_weight_error");
        return 0;
    }

    std::vector<uint64_t> xb(primary_n + 1, 0);
    std::vector<int> rb(primary_n + 1, 0);
    std::vector<char> xhas(primary_n + 1, 0);
    bool bad = false;
    for (int i = 0; i < score_m; ++i) {
        uint64_t row = score_rows[i];
        int rhs = int((err >> i) & U128(1)) ^ score_const[i];
        while (row) {
            int p = 64 - __builtin_clzll(row);
            if (xhas[p]) {
                row ^= xb[p];
                rhs ^= rb[p];
            } else {
                xb[p] = row;
                rb[p] = rhs;
                xhas[p] = 1;
                break;
            }
        }
        if (!row && rhs) bad = true;
    }
    if (bad) {
        unknown("cannot_solve_primary");
        return 0;
    }
    uint64_t xmask = 0;
    for (int p = 1; p <= primary_n; ++p) {
        if (!xhas[p]) continue;
        int val = rb[p];
        uint64_t rest = xb[p] ^ (1ULL << (p - 1));
        for (int q = 1; q < p; ++q) {
            if (((rest >> (q - 1)) & 1ULL) && ((xmask >> (q - 1)) & 1ULL)) val ^= 1;
        }
        if (val) xmask |= 1ULL << (p - 1);
    }

    std::vector<int8_t> asg(nvars + 1, -1);
    for (int v = 1; v <= primary_n; ++v) asg[v] = (xmask >> (v - 1)) & 1ULL;
    for (int v = primary_n + 1; v <= nvars; ++v) {
        if (!has[v]) continue;
        LinRow r = basis[v];
        flip_bit(r.w, v);
        while (true) {
            int p = highest_set_range(r.w, primary_n + 1, nvars);
            if (!p) break;
            xor_row(r, basis[p]);
        }
        int val = r.rhs;
        for (int j = 1; j <= primary_n; ++j) if (get_bit(r.w, j)) val ^= asg[j];
        asg[v] = val;
    }
    for (int i = 0; i < score_m; ++i) asg[first_score + i] = int((err >> i) & U128(1));

    if (!finish_assignment(clauses, asg) || !validate(clauses, asg)) {
        unknown("completion_or_validation_failed");
        return 0;
    }

    std::cout << "s SATISFIABLE\n";
    std::cout << "v";
    for (int v = 1; v <= nvars; ++v) {
        int lit = asg[v] ? v : -v;
        std::cout << ' ' << lit;
        if (v % 20 == 0 && v != nvars) std::cout << "\nv";
    }
    std::cout << " 0\n";
    return 10;
}
