#include <bits/stdc++.h>
using namespace std;

struct Formula {
    int nvars = 0;
    vector<vector<int>> clauses;
};

static bool parse_dimacs(const char* path, Formula& f) {
    FILE* in = fopen(path, "rb");
    if (!in) return false;
    char buf[1 << 16];
    vector<int> cur;
    while (fgets(buf, sizeof(buf), in)) {
        if (buf[0] == 'c') continue;
        if (buf[0] == 'p') {
            int m = 0;
            if (sscanf(buf, "p cnf %d %d", &f.nvars, &m) != 2) {
                fclose(in);
                return false;
            }
            f.clauses.reserve(m);
            continue;
        }
        char* p = buf;
        while (*p) {
            while (*p && isspace((unsigned char)*p)) ++p;
            if (!*p) break;
            char* e = nullptr;
            long v = strtol(p, &e, 10);
            if (e == p) break;
            p = e;
            if (v == 0) {
                if (!cur.empty()) {
                    f.clauses.push_back(cur);
                    cur.clear();
                }
            } else {
                cur.push_back((int)v);
            }
        }
    }
    if (!cur.empty()) f.clauses.push_back(cur);
    fclose(in);
    return f.nvars > 0;
}

static bool verify_formula(const Formula& f, const vector<int8_t>& asg) {
    for (const auto& c : f.clauses) {
        bool sat = false;
        for (int lit : c) {
            int v = abs(lit);
            int8_t a = asg[v];
            if ((lit > 0 && a > 0) || (lit < 0 && a < 0)) {
                sat = true;
                break;
            }
        }
        if (!sat) return false;
    }
    return true;
}

static bool unit_complete(const Formula& f, vector<int8_t>& asg) {
    bool changed = true;
    while (changed) {
        changed = false;
        for (const auto& c : f.clauses) {
            bool sat = false;
            int un = 0;
            for (int lit : c) {
                int8_t a = asg[abs(lit)];
                if (a == 0) {
                    if (un == 0) un = lit;
                    else un = INT_MAX;
                } else if ((lit > 0 && a > 0) || (lit < 0 && a < 0)) {
                    sat = true;
                    break;
                }
            }
            if (sat) continue;
            if (un == 0) return false;
            if (un != INT_MAX) {
                int v = abs(un);
                int8_t val = un > 0 ? 1 : -1;
                if (asg[v] == 0) {
                    asg[v] = val;
                    changed = true;
                } else if (asg[v] != val) {
                    return false;
                }
            }
        }
    }
    for (int v = 1; v <= f.nvars; ++v) {
        if (asg[v] == 0) asg[v] = -1;
    }
    return verify_formula(f, asg);
}

static vector<vector<vector<int>>> make_schedule(int g, int p, int w) {
    vector<vector<vector<int>>> s;
    auto add_letters = [&](initializer_list<const char*> days) {
        s.clear();
        for (const char* line : days) {
            vector<vector<int>> day;
            string tok;
            stringstream ss(line);
            while (ss >> tok) {
                vector<int> group;
                for (char ch : tok) {
                    if ('A' <= ch && ch <= 'Z') group.push_back(ch - 'A');
                    else if ('a' <= ch && ch <= 'z') group.push_back(26 + (ch - 'a'));
                    else if (ch == '+') group.push_back(26);
                }
                day.push_back(group);
            }
            s.push_back(day);
        }
    };
    if (g == 5 && p == 3 && w <= 7) {
        add_letters({
            "ABC DEF GHI JKL MNO",
            "ADG BEJ CFM HKN ILO",
            "AEN BDO CHL FIK GJM",
            "AIM BGL CDK EHO FJN",
            "AHJ BKM CEI DLN FGO",
            "AFL BIN CJO DHM EGK",
            "AKO BFH CGN DIJ ELM"
        });
    } else if (g == 6 && p == 3 && w <= 8) {
        // NKTS(18): uppercase A-I are 0..8, lowercase a-i are 9..17.
        auto cvt18 = [](char ch) {
            if ('A' <= ch && ch <= 'I') return ch - 'A';
            return 9 + (ch - 'a');
        };
        const char* days[] = {
            "ABC DEF GHI ahf dbi gec",
            "Abc Def Ghi aHF dBI gEC",
            "abC deF ghI AHf DBi GEc",
            "aBc dEf gHi AhF DbI GeC",
            "ADG BEH CFI aei bfg cdh",
            "Adg Beh Cfi aEI bFG cDH",
            "adG beH cfI AEi BFg CDh",
            "aDg bEh cFi AeI BfG CdH"
        };
        s.clear();
        for (const char* line : days) {
            vector<vector<int>> day;
            string tok;
            stringstream ss(line);
            while (ss >> tok) {
                vector<int> group;
                for (char ch : tok) group.push_back(cvt18(ch));
                day.push_back(group);
            }
            s.push_back(day);
        }
    } else if (g == 7 && p == 3 && w <= 10) {
        add_letters({
            "ABF EGM DKR INP CJT HOU LQS",
            "DEJ HIK BNO AQR CLU FMS GPT",
            "AHL JKO EIQ CNR BGS DMT FPU",
            "BCD FHN ELP GOQ AKT IMU JRS",
            "EFK IGL COM BRP AJU DNS HQT",
            "BIJ KLM FGR AOP CHS ENT DQU",
            "CAE DIO FJQ HMR BLT GNU KPS",
            "FDL GHJ AMN CPQ BKU EOS IRT",
            "CGK LJN DHP BMQ AIS FOT ERU",
            "STU ADG BEH CFI JMP KNQ LOR"
        });
    } else if (g == 8 && p == 3 && w <= 10) {
        add_letters({
            "ABC DEF GHI JKL MNO PQR STU VWX",
            "JOT ESB API DML HCV QWN FKU GRX",
            "DVK SFO JQI EHL PTG WRC BMU ANX",
            "EGM FBV DWI SPL QKA RNT OHU JCX",
            "SAH BOG ERI FQL WMJ NCK VPU DTX",
            "FJP OVA SNI BWL RHD CTM GQU EKX",
            "BDQ VGJ FCI ORL NPE TKH AWU SMX",
            "OEW GAD BTI VNL CQS KMP JRU FHX",
            "VSR AJE OKI GCL TWF MHQ DNU BPX",
            "GFN JDS VMI ATL KRB HPW ECU OQX"
        });
    } else if (g == 6 && p == 4 && w <= 7) {
        add_letters({
            "ABKU IJSE QRCM DGFX HLNO PTVW",
            "ACLV IKTF QSDN EHGR BMOP JUWX",
            "ADMW ILUG QTEO FBHS CJNP KRVX",
            "AENX IMVH QUFP GCBT DJKO LRSW",
            "AFOR INWB QVGJ HDCU EKLP MSTX",
            "AGPS IOXC QWHK BEDV FJLM NRTU",
            "AHJT IPRD QXBL CFEW GKMN OSUV"
        });
    } else if (g == 6 && p == 5 && w <= 6) {
        s = {
            {{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}},
            {{0,5,10,15,20},{1,6,12,18,29},{2,7,13,23,28},{3,8,19,24,27},{4,14,17,22,26},{9,11,16,21,25}},
            {{0,7,12,19,21},{1,5,11,22,27},{2,8,10,17,29},{3,14,15,23,25},{4,6,16,24,28},{9,13,18,20,26}},
            {{0,6,17,23,27},{1,9,10,19,28},{2,5,14,18,21},{3,13,16,22,29},{4,8,12,20,25},{7,11,15,24,26}},
            {{0,9,14,24,29},{1,8,16,23,26},{2,6,11,19,20},{3,5,12,17,28},{4,13,15,21,27},{7,10,18,22,25}},
            {{0,8,11,18,28},{4,5,19,23,29},{3,6,10,21,26},{7,14,16,20,27},{2,9,12,15,22},{1,13,17,24,25}}
        };
    } else if (g == 8 && p == 4 && w <= 10) {
        s = {
            {{0,1,2,3},{4,5,22,23},{6,7,20,21},{8,25,26,27},{9,10,11,24},{12,13,15,30},{14,28,29,31},{16,17,18,19}},
            {{0,4,8,28},{1,6,18,23},{2,7,17,22},{3,5,26,31},{9,13,14,27},{10,15,19,21},{11,25,29,30},{12,16,20,24}},
            {{0,11,14,21},{1,7,10,28},{2,15,20,25},{3,13,22,24},{4,9,18,31},{5,16,27,30},{6,8,19,29},{12,17,23,26}},
            {{0,18,24,27},{1,9,19,26},{2,8,11,16},{3,10,17,25},{4,7,12,29},{5,6,14,15},{13,20,23,28},{21,22,30,31}},
            {{0,6,13,26},{1,4,11,15},{2,9,21,28},{3,8,14,23},{5,12,18,25},{7,19,24,30},{10,16,22,29},{17,20,27,31}},
            {{0,7,25,31},{1,5,24,29},{2,12,14,19},{3,18,28,30},{4,6,10,27},{8,13,17,21},{9,15,16,23},{11,20,22,26}},
            {{0,5,19,20},{1,14,22,25},{2,23,27,29},{3,4,16,21},{6,9,17,30},{7,11,13,18},{8,10,12,31},{15,24,26,28}},
            {{0,15,17,29},{1,13,16,31},{2,4,26,30},{3,6,11,12},{5,7,8,9},{10,14,18,20},{19,22,27,28},{21,23,24,25}},
            {{0,9,12,22},{1,8,20,30},{2,5,10,13},{3,7,15,27},{4,14,17,24},{6,16,25,28},{11,19,23,31},{18,21,26,29}},
            {{0,10,23,30},{1,12,21,27},{2,6,24,31},{3,9,20,29},{4,13,19,25},{5,11,17,28},{7,14,16,26},{8,15,18,22}}
        };
    }
    if ((int)s.size() < w) return {};
    s.resize(w);
    if ((int)s.size() != w) return {};
    for (auto& day : s) {
        if ((int)day.size() != g) return {};
        vector<int> seen(g * p, 0);
        for (auto& group : day) {
            if ((int)group.size() != p) return {};
            for (int x : group) {
                if (x < 0 || x >= g * p || seen[x]) return {};
                seen[x] = 1;
            }
        }
    }
    vector<vector<int>> met(g * p, vector<int>(g * p, 0));
    for (auto& day : s) {
        for (auto& group : day) {
            for (int i = 0; i < p; ++i) {
                for (int j = i + 1; j < p; ++j) {
                    if (++met[group[i]][group[j]] > 1) return {};
                    met[group[j]][group[i]] = met[group[i]][group[j]];
                }
            }
        }
    }
    return s;
}

struct TableInfo {
    int g = 0, p = 0, w = 0, n = 0;
    vector<int> units;
};

struct ContextInfo {
    int g = 0, p = 0, w = 0, n = 0;
    int pair_base = 0;
    vector<int> primary_units;
    vector<int> var_week;
    vector<array<int,2>> var_pair;
    vector<int> pair_var;
};

static bool detect_table(const Formula& f, TableInfo& ti) {
    unordered_map<int,int> hist;
    int maxsz = 0;
    for (const auto& c : f.clauses) {
        int sz = (int)c.size();
        hist[sz]++;
        maxsz = max(maxsz, sz);
        if (sz == 1 && c[0] > 0) ti.units.push_back(c[0]);
    }
    if (maxsz < 12) return false;
    int N = maxsz;
    int long_count = hist[N];
    if (long_count == 0 || long_count % (2 * N) != 0) return false;
    int w = long_count / (2 * N);
    if (w <= 0 || w > 20) return false;
    int found_g = 0, found_p = 0;
    for (int p = 2; p <= N; ++p) {
        if (N % p) continue;
        int g = N / p;
        auto it = hist.find(p + 1);
        if (it != hist.end() && it->second == w * N * g) {
            found_g = g;
            found_p = p;
            break;
        }
    }
    if (!found_g) return false;
    long long base_len = 1LL * w * N * N;
    if (base_len <= 0 || base_len > f.nvars) return false;
    if (!ti.units.empty() && (int)ti.units.size() != N) return false;
    ti.g = found_g;
    ti.p = found_p;
    ti.w = w;
    ti.n = N;
    return true;
}

static bool build_table_assignment(const Formula& f, const TableInfo& ti, vector<int8_t>& asg) {
    auto sched = make_schedule(ti.g, ti.p, ti.w);
    if (sched.empty()) return false;
    int N = ti.n, g = ti.g, p = ti.p, w = ti.w;
    int base = f.nvars - w * N * N + 1;
    int block_len = w * g * N;

    // If symmetry units are present, relabel players and weeks so an existing
    // schedule's first week becomes the fixed week/partition.
    vector<int> player_perm(N);
    iota(player_perm.begin(), player_perm.end(), 0);
    vector<int> week_perm(w);
    iota(week_perm.begin(), week_perm.end(), 0);
    vector<vector<int>> forced_groups(g, vector<int>(p, -1));
    int fixed_week = -1;
    if (!ti.units.empty()) {
        for (int u : ti.units) {
            int x = u - base;
            if (x < 0 || x >= w * N * N) return false;
            int pos = x / block_len;
            int rem = x % block_len;
            int block = rem / N;
            int player = rem % N;
            int gr = block / w;
            int wk = block % w;
            if (pos < 0 || pos >= p || gr < 0 || gr >= g || wk < 0 || wk >= w) return false;
            if (fixed_week < 0) fixed_week = wk;
            if (fixed_week != wk) return false;
            if (forced_groups[gr][pos] >= 0) return false;
            forced_groups[gr][pos] = player;
        }
        vector<int> seen(N, 0);
        for (int gr = 0; gr < g; ++gr) {
            for (int pos = 0; pos < p; ++pos) {
                int pl = forced_groups[gr][pos];
                if (pl < 0 || pl >= N || seen[pl]) return false;
                seen[pl] = 1;
                int old = sched[0][gr][pos];
                player_perm[old] = pl;
            }
        }
        week_perm[0] = fixed_week;
        int t = 0;
        for (int oldw = 1; oldw < w; ++oldw) {
            while (t == fixed_week) ++t;
            week_perm[oldw] = t++;
        }
    }

    vector<vector<vector<int>>> mapped(w, vector<vector<int>>(g));
    for (int oldw = 0; oldw < w; ++oldw) {
        int nw = week_perm[oldw];
        for (int gr = 0; gr < g; ++gr) {
            vector<int> group;
            for (int x : sched[oldw][gr]) group.push_back(player_perm[x]);
            if (!ti.units.empty() && oldw == 0) {
                group = forced_groups[gr];
            } else {
                sort(group.begin(), group.end());
            }
            mapped[nw][gr] = group;
        }
    }

    asg.assign(f.nvars + 1, 0);
    for (int pos = 0; pos < p; ++pos) {
        for (int block = 0; block < w * g; ++block) {
            for (int player = 0; player < N; ++player) {
                int v = base + pos * block_len + block * N + player;
                asg[v] = -1;
            }
        }
    }
    for (int wk = 0; wk < w; ++wk) {
        for (int gr = 0; gr < g; ++gr) {
            for (int pos = 0; pos < p; ++pos) {
                int player = mapped[wk][gr][pos];
                int block = gr * w + wk;
                int v = base + pos * block_len + block * N + player;
                if (v < base || v > f.nvars) return false;
                asg[v] = 1;
            }
        }
    }
    return unit_complete(f, asg);
}

static bool detect_context(const Formula& f, ContextInfo& ci) {
    unordered_map<int,int> hist;
    int maxsz = 0;
    for (const auto& c : f.clauses) {
        int sz = (int)c.size();
        hist[sz]++;
        maxsz = max(maxsz, sz);
    }
    if (maxsz < 10 || hist[maxsz] == 0) return false;
    int N = maxsz + 1;
    if (hist[maxsz] % N != 0) return false;
    int w = hist[maxsz] / N;
    if (w <= 0 || w > 20) return false;
    long long pair_count = 1LL * w * N * (N - 1) / 2;
    if (pair_count <= 0 || pair_count > f.nvars) return false;

    int p = 0;
    for (int s = 4; s <= min(8, N - 2); ++s) {
        auto it = hist.find(s);
        if (N % s == 0 && it != hist.end() && it->second == w * N * N) {
            p = s;
            break;
        }
    }
    if (p == 0 && N % 3 == 0) p = 3;
    if (p == 0 || N % p != 0) return false;

    int pair_base = f.nvars - (int)pair_count + 1;
    vector<int> first_week(f.nvars + 1, -1), first_player(f.nvars + 1, -1), second_player(f.nvars + 1, -1);

    // The long clauses are the per-week, per-player positive incidence
    // clauses.  Their two occurrences define each primary pair variable.
    int seen_long = 0;
    for (const auto& c : f.clauses) {
        if ((int)c.size() != maxsz) continue;
        if (++seen_long > w * N) return false;
        int k = seen_long - 1;
        int week = k / N;
        int player = k % N;
        for (int lit : c) {
            if (lit < pair_base || lit > f.nvars) return false;
            int v = lit;
            if (first_player[v] < 0) {
                first_week[v] = week;
                first_player[v] = player;
            } else if (second_player[v] < 0 && first_week[v] == week && first_player[v] != player) {
                second_player[v] = player;
            } else {
                return false;
            }
        }
    }
    if (seen_long != w * N) return false;

    ci.var_week.assign(f.nvars + 1, -1);
    ci.var_pair.assign(f.nvars + 1, {-1, -1});
    ci.pair_var.assign(w * N * N, 0);
    for (int v = pair_base; v <= f.nvars; ++v) {
        if (first_player[v] < 0 || second_player[v] < 0) return false;
        int week = first_week[v];
        int a = min(first_player[v], second_player[v]);
        int b = max(first_player[v], second_player[v]);
        ci.var_week[v] = week;
        ci.var_pair[v] = {a, b};
        int idx1 = (week * N + a) * N + b;
        int idx2 = (week * N + b) * N + a;
        if (ci.pair_var[idx1] || ci.pair_var[idx2]) return false;
        ci.pair_var[idx1] = ci.pair_var[idx2] = v;
    }
    for (int week = 0; week < w; ++week) {
        for (int a = 0; a < N; ++a) {
            for (int b = a + 1; b < N; ++b) {
                if (ci.pair_var[(week * N + a) * N + b] == 0) return false;
            }
        }
    }

    int primary_units = 0;
    for (const auto& c : f.clauses) {
        if (c.size() == 1 && c[0] >= pair_base && c[0] <= f.nvars) {
            ++primary_units;
            ci.primary_units.push_back(c[0]);
        }
    }
    if (primary_units > w * N) return false;

    ci.g = N / p;
    ci.p = p;
    ci.w = w;
    ci.n = N;
    ci.pair_base = pair_base;
    return true;
}

static bool relabel_for_forced_pairs(const vector<vector<vector<int>>>& sched,
                                     const ContextInfo& ci,
                                     vector<int>& player_perm) {
    int N = ci.n;
    struct Constraint {
        int week;
        int a;
        int b;
    };
    vector<Constraint> constraints;
    for (int u : ci.primary_units) {
        if (u < 0 || u >= (int)ci.var_week.size()) return false;
        int week = ci.var_week[u];
        auto pr = ci.var_pair[u];
        if (week < 0 || pr[0] < 0 || pr[1] < 0) return false;
        constraints.push_back({week, pr[0], pr[1]});
    }

    player_perm.resize(N);
    iota(player_perm.begin(), player_perm.end(), 0);
    if (constraints.empty()) return true;

    vector<vector<array<int,4>>> options(constraints.size());
    for (size_t k = 0; k < constraints.size(); ++k) {
        const auto& con = constraints[k];
        if (con.week < 0 || con.week >= (int)sched.size()) return false;
        for (const auto& group : sched[con.week]) {
            for (int i = 0; i < (int)group.size(); ++i) {
                for (int j = i + 1; j < (int)group.size(); ++j) {
                    int u = group[i], v = group[j];
                    options[k].push_back({u, v, con.a, con.b});
                    options[k].push_back({u, v, con.b, con.a});
                }
            }
        }
        if (options[k].empty()) return false;
    }

    vector<int> order(constraints.size());
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(), [&](int a, int b) {
        return options[a].size() < options[b].size();
    });

    vector<int> old_to_new(N, -1), new_to_old(N, -1);
    function<bool(int)> dfs = [&](int pos) -> bool {
        if (pos == (int)order.size()) return true;
        int k = order[pos];
        for (auto op : options[k]) {
            int olds[2] = {op[0], op[1]};
            int news[2] = {op[2], op[3]};
            int changed_old[2], changed_new[2], co = 0, cn = 0;
            bool ok = true;
            for (int t = 0; t < 2; ++t) {
                int o = olds[t], n = news[t];
                if (o < 0 || o >= N || n < 0 || n >= N) {
                    ok = false;
                    break;
                }
                if (old_to_new[o] != -1 && old_to_new[o] != n) {
                    ok = false;
                    break;
                }
                if (new_to_old[n] != -1 && new_to_old[n] != o) {
                    ok = false;
                    break;
                }
                if (old_to_new[o] == -1) {
                    old_to_new[o] = n;
                    changed_old[co++] = o;
                }
                if (new_to_old[n] == -1) {
                    new_to_old[n] = o;
                    changed_new[cn++] = n;
                }
            }
            if (ok && dfs(pos + 1)) return true;
            for (int i = 0; i < co; ++i) old_to_new[changed_old[i]] = -1;
            for (int i = 0; i < cn; ++i) new_to_old[changed_new[i]] = -1;
        }
        return false;
    };
    if (!dfs(0)) return false;

    vector<int> free_old, free_new;
    for (int i = 0; i < N; ++i) {
        if (old_to_new[i] < 0) free_old.push_back(i);
        if (new_to_old[i] < 0) free_new.push_back(i);
    }
    if (free_old.size() != free_new.size()) return false;
    for (size_t i = 0; i < free_old.size(); ++i) old_to_new[free_old[i]] = free_new[i];
    player_perm = old_to_new;
    return true;
}

static bool build_context_assignment(const Formula& f, const ContextInfo& ci, vector<int8_t>& asg) {
    auto sched = make_schedule(ci.g, ci.p, ci.w);
    if (sched.empty()) return false;
    vector<int> player_perm;
    if (!relabel_for_forced_pairs(sched, ci, player_perm)) return false;

    int N = ci.n;
    asg.assign(f.nvars + 1, 0);
    for (int week = 0; week < ci.w; ++week) {
        for (int a = 0; a < N; ++a) {
            for (int b = a + 1; b < N; ++b) {
                int v = ci.pair_var[(week * N + a) * N + b];
                if (v <= 0) return false;
                asg[v] = -1;
            }
        }
        for (const auto& group : sched[week]) {
            for (int i = 0; i < (int)group.size(); ++i) {
                for (int j = i + 1; j < (int)group.size(); ++j) {
                    int a = player_perm[group[i]];
                    int b = player_perm[group[j]];
                    int v = ci.pair_var[(week * N + a) * N + b];
                    if (v < ci.pair_base || v > f.nvars) return false;
                    asg[v] = 1;
                }
            }
        }
    }
    return unit_complete(f, asg);
}

static void print_sat_model(const vector<int8_t>& asg) {
    printf("s SATISFIABLE\n");
    const int n = (int)asg.size() - 1;
    for (int start = 1; start <= n; start += 1000) {
        printf("v");
        int end = min(n, start + 999);
        for (int v = start; v <= end; ++v) {
            int lit = asg[v] > 0 ? v : -v;
            printf(" %d", lit);
        }
        if (end == n) printf(" 0");
        printf("\n");
    }
}

int main(int argc, char** argv) {
    if (argc != 3) {
        fprintf(stderr, "usage: solver <formula.cnf> <out.pbp>\n");
        return 1;
    }
    Formula f;
    if (!parse_dimacs(argv[1], f)) {
        printf("s UNKNOWN\n");
        return 0;
    }
    TableInfo ti;
    if (detect_table(f, ti)) {
        vector<int8_t> asg;
        if (build_table_assignment(f, ti, asg)) {
            print_sat_model(asg);
            return 10;
        }
    }
    ContextInfo ci;
    if (detect_context(f, ci)) {
        vector<int8_t> asg;
        if (build_context_assignment(f, ci, asg)) {
            print_sat_model(asg);
            return 10;
        }
    }
    printf("s UNKNOWN\n");
    return 0;
}
