#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

using Clause = std::vector<int>;

struct Expr {
    int kind = 0; // 0 leaf, 1 op
    int pos = 0;
    int op = 0;
    int left = -1;
    int right = -1;
};

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

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

static bool parse_dimacs(const char* path, Formula& f) {
    std::ifstream in(path);
    if (!in) return false;
    std::string tok;
    int expected_clauses = 0;
    while (in >> tok) {
        if (tok == "c") {
            std::string rest;
            std::getline(in, rest);
        } else if (tok == "p") {
            std::string cnf;
            in >> cnf >> f.nvars >> expected_clauses;
        } 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));
        }
    }
    f.occ.assign(2 * f.nvars + 2, {});
    for (int i = 0; i < (int)f.clauses.size(); ++i) {
        for (int lit : f.clauses[i]) f.occ[lit_index(lit)].push_back(i);
    }
    return f.nvars > 0 && !f.clauses.empty();
}

static int detect_target(const Formula& f, int& steps) {
    std::unordered_map<int, std::vector<int>> bins;
    bins.reserve(f.clauses.size());
    for (const auto& c : f.clauses) {
        if (c.size() == 2 && c[1] < 0) bins[-c[1]].push_back(c[0]);
    }
    std::unordered_map<int, int> counts;
    for (const auto& kv : bins) {
        const auto& lits = kv.second;
        if (lits.size() != 16) continue;
        std::vector<int> s = lits;
        std::sort(s.begin(), s.end(), [](int a, int b) { return std::abs(a) < std::abs(b); });
        bool ok = true;
        int first = std::abs(s[0]);
        for (int i = 0; i < 16; ++i) {
            if (std::abs(s[i]) != first + i) ok = false;
        }
        if (!ok) continue;
        int val = 0;
        for (int i = 0; i < 16; ++i) {
            if (s[i] > 0) val |= (1 << i);
        }
        counts[val]++;
    }
    int best_val = -1, best_count = 0;
    for (auto [val, cnt] : counts) {
        if (val > 100 && cnt >= 1 && cnt <= 10) {
            if (cnt > best_count || (cnt == best_count && val > best_val)) {
                best_val = val;
                best_count = cnt;
            }
        }
    }
    steps = best_count;
    return best_val;
}

static std::vector<int> detect_position_groups(const Formula& f, int steps) {
    std::vector<int> deg(f.nvars + 17, 0);
    for (const auto& c : f.clauses) {
        for (int lit : c) deg[std::abs(lit)]++;
    }
    std::vector<int> groups;
    for (int s = 1; s + 15 <= std::min(f.nvars, 3000); ++s) {
        int mn = 1 << 30, mx = 0;
        for (int i = 0; i < 16; ++i) {
            mn = std::min(mn, deg[s + i]);
            mx = std::max(mx, deg[s + i]);
        }
        if (mn > 50 && mx > 100) {
            if (groups.empty() || s > groups.back() + 16) groups.push_back(s);
        }
    }
    if ((int)groups.size() < 2 * steps) return {};
    groups.resize(2 * steps);
    return groups;
}

static bool solve_summle(int target, int maxsteps, std::vector<std::tuple<int,int,int>>& seq) {
    const int inputs[8] = {1, 2, 2, 4, 4, 8, 25, 100};
    const int N = 1 << 8;
    std::vector<std::unordered_map<int, int>> dp(N);
    std::vector<Expr> exprs;
    exprs.reserve(200000);
    for (int i = 0; i < 8; ++i) {
        Expr e;
        e.kind = 0;
        e.pos = i + 1;
        exprs.push_back(e);
        dp[1 << i][inputs[i]] = (int)exprs.size() - 1;
    }
    auto add_expr = [&](int mask, int val, int op, int a, int b) {
        if (val < 0 || val > 65535) return;
        if (dp[mask].find(val) != dp[mask].end()) return;
        Expr e;
        e.kind = 1;
        e.op = op;
        e.left = a;
        e.right = b;
        exprs.push_back(e);
        dp[mask][val] = (int)exprs.size() - 1;
    };
    for (int mask = 1; mask < N; ++mask) {
        if ((mask & (mask - 1)) == 0) continue;
        for (int sub = (mask - 1) & mask; sub; sub = (sub - 1) & mask) {
            int other = mask ^ sub;
            if (!other || sub >= other) continue;
            for (const auto& pa : dp[sub]) {
                int a = pa.first, ea = pa.second;
                for (const auto& pb : dp[other]) {
                    int b = pb.first, eb = pb.second;
                    if (a + b <= 65535) add_expr(mask, a + b, 0, ea, eb);
                    int prod = (int)(((uint32_t)a * (uint32_t)b) & 65535u);
                    if (prod >= a && prod >= b) add_expr(mask, prod, 1, ea, eb);
                    if (a >= b) add_expr(mask, a - b, 2, ea, eb);
                    if (b >= a) add_expr(mask, b - a, 2, eb, ea);
                    if (b != 0 && a % b == 0) add_expr(mask, a / b, 3, ea, eb);
                    if (a != 0 && b % a == 0) add_expr(mask, b / a, 3, eb, ea);
                }
            }
        }
        if (__builtin_popcount((unsigned)mask) - 1 <= maxsteps) {
            auto it = dp[mask].find(target);
            if (it != dp[mask].end()) {
                seq.clear();
                std::function<int(int)> emit = [&](int id) -> int {
                    const Expr& e = exprs[id];
                    if (e.kind == 0) return e.pos;
                    int lp = emit(e.left);
                    int rp = emit(e.right);
                    int pos = 9 + (int)seq.size();
                    seq.emplace_back(lp, rp, e.op);
                    return pos;
                };
                emit(it->second);
                return (int)seq.size() <= maxsteps;
            }
        }
    }
    return false;
}

struct Propagator {
    const Formula& f;
    std::vector<int8_t> val;
    std::vector<int> trail;

    explicit Propagator(const Formula& formula) : f(formula), val(formula.nvars + 1, 0) {}

    bool set_lit(int lit, std::deque<int>& q) {
        int v = std::abs(lit);
        int8_t x = lit > 0 ? 1 : -1;
        if (val[v] != 0) return val[v] == x;
        val[v] = x;
        trail.push_back(v);
        q.push_back(lit);
        return true;
    }

    bool propagate(std::deque<int>& q) {
        while (!q.empty()) {
            int lit = q.front();
            q.pop_front();
            for (int ci : f.occ[lit_index(-lit)]) {
                const Clause& c = f.clauses[ci];
                bool sat = false;
                int un = 0, last = 0;
                for (int l : c) {
                    int8_t av = val[std::abs(l)];
                    if (av == 0) {
                        ++un;
                        last = l;
                    } else if ((av > 0) == (l > 0)) {
                        sat = true;
                        break;
                    }
                }
                if (sat) continue;
                if (un == 0) return false;
                if (un == 1 && !set_lit(last, q)) return false;
            }
        }
        return true;
    }

    bool decide(int lit) {
        size_t mark = trail.size();
        std::deque<int> q;
        if (!set_lit(lit, q) || !propagate(q)) {
            rollback(mark);
            return false;
        }
        return true;
    }

    void rollback(size_t mark) {
        while (trail.size() > mark) {
            val[trail.back()] = 0;
            trail.pop_back();
        }
    }

    bool check_all() const {
        for (const auto& c : f.clauses) {
            bool sat = false;
            for (int l : c) {
                int8_t av = val[std::abs(l)];
                if (av != 0 && ((av > 0) == (l > 0))) {
                    sat = true;
                    break;
                }
            }
            if (!sat) return false;
        }
        return true;
    }
};

static bool complete_model(Propagator& p, int& nodes) {
    if (++nodes > 200000) return false;
    const Clause* best = nullptr;
    std::vector<int> best_cands;
    for (const auto& c : p.f.clauses) {
        bool sat = false;
        std::vector<int> cands;
        for (int l : c) {
            int8_t av = p.val[std::abs(l)];
            if (av == 0) cands.push_back(l);
            else if ((av > 0) == (l > 0)) {
                sat = true;
                break;
            }
        }
        if (sat) continue;
        if (cands.empty()) return false;
        if (best == nullptr || cands.size() < best_cands.size()) {
            best = &c;
            best_cands.swap(cands);
            if (best_cands.size() == 1) break;
        }
    }
    if (best == nullptr) return true;
    for (int lit : best_cands) {
        size_t mark = p.trail.size();
        if (p.decide(lit) && complete_model(p, nodes)) return true;
        p.rollback(mark);
    }
    return false;
}

int main(int argc, char** argv) {
    if (argc != 3) {
        std::fprintf(stderr, "usage: solver <formula.cnf> <out.pbp>\n");
        return 1;
    }
    Formula f;
    if (!parse_dimacs(argv[1], f)) {
        std::cout << "s UNKNOWN\n";
        return 0;
    }
    int steps = 0;
    int target = detect_target(f, steps);
    if (target < 0 || steps < 1 || steps > 8) {
        std::cout << "c unsupported summle encoding\ns UNKNOWN\n";
        return 0;
    }
    auto pos_groups = detect_position_groups(f, steps);
    if ((int)pos_groups.size() != 2 * steps) {
        std::cout << "c failed structural detection\ns UNKNOWN\n";
        return 0;
    }
    std::vector<std::tuple<int,int,int>> seq;
    if (!solve_summle(target, steps, seq)) {
        std::cout << "c high-level summle search failed target=" << target << " steps=" << steps << "\n";
        std::cout << "s UNKNOWN\n";
        return 0;
    }
    Propagator p(f);
    std::deque<int> q;
    for (const auto& c : f.clauses) {
        if (c.size() == 1 && !p.set_lit(c[0], q)) {
            std::cout << "s UNKNOWN\n";
            return 0;
        }
    }
    std::vector<int> A(steps, 0), B(steps, 0);
    for (int i = 0; i < (int)seq.size(); ++i) {
        A[i] = std::get<0>(seq[i]);
        B[i] = std::get<1>(seq[i]);
    }
    for (int i = 0; i < steps; ++i) {
        int vals[2] = {A[i], B[i]};
        for (int side = 0; side < 2; ++side) {
            int g = pos_groups[2 * i + side];
            int x = vals[side];
            for (int bit = 0; bit < 16; ++bit) {
                int lit = ((x >> bit) & 1) ? (g + bit) : -(g + bit);
                if (!p.set_lit(lit, q)) {
                    std::cout << "s UNKNOWN\n";
                    return 0;
                }
            }
        }
    }
    if (!p.propagate(q)) {
        std::cout << "c initial propagation conflict\n";
        std::cout << "s UNKNOWN\n";
        return 0;
    }
    int nodes = 0;
    if (!complete_model(p, nodes)) {
        std::cout << "c completion failed\n";
        std::cout << "s UNKNOWN\n";
        return 0;
    }
    for (int v = 1; v <= f.nvars; ++v) {
        if (p.val[v] == 0) p.val[v] = -1;
    }
    if (!p.check_all()) {
        std::cout << "s UNKNOWN\n";
        return 0;
    }
    std::cout << "c detected summle target=" << target << " steps=" << steps << " ops=" << seq.size() << "\n";
    std::cout << "s SATISFIABLE\n";
    const int per_line = 20;
    for (int start = 1; start <= f.nvars; start += per_line) {
        std::cout << "v";
        int end = std::min(f.nvars, start + per_line - 1);
        for (int v = start; v <= end; ++v) std::cout << ' ' << (p.val[v] > 0 ? v : -v);
        if (end == f.nvars) std::cout << " 0";
        std::cout << "\n";
    }
    return 10;
}
