#!/usr/bin/env python3
import itertools
import math
import sys
import time


def edge_index(n):
    idx = {}
    pairs = []
    k = 0
    for i in range(n):
        for j in range(i + 1, n):
            idx[i, j] = k
            pairs.append((i, j))
            k += 1
    return idx, pairs


def clique_masks(n, r, idx):
    out = []
    for verts in itertools.combinations(range(n), r):
        m = 0
        for a, b in itertools.combinations(verts, 2):
            m |= 1 << idx[a, b]
        out.append(m)
    return out


class Solver:
    def __init__(self, n, s, t, degree_bounds=True):
        self.n = n
        self.s = s
        self.t = t
        self.m = n * (n - 1) // 2
        self.allmask = (1 << self.m) - 1
        self.idx, self.pairs = edge_index(n)
        self.pos = clique_masks(n, s, self.idx)
        self.neg = clique_masks(n, t, self.idx)
        self.inc = []
        for v in range(n):
            m = 0
            for u in range(n):
                if u == v:
                    continue
                a, b = sorted((u, v))
                m |= 1 << self.idx[a, b]
            self.inc.append(m)
        self.deg = []
        if degree_bounds and s == 3:
            # Formula is no blue K3 and no red K_t. In the blue graph,
            # max degree is t-1. Exact threshold instances additionally have
            # min degree n - R(3,t-1), using known smaller Ramsey values.
            known = {3: 6, 4: 9, 5: 14, 6: 18}
            if t in known:
                self.deg.append((0, t - 1))
                self.deg.append((n - known[t - 1], n - 1))
        self.nodes = 0
        self.start = time.time()

    def propagate(self, true, false):
        changed = True
        while changed:
            changed = False
            unknown = self.allmask & ~(true | false)
            for cm in self.pos:
                if cm & true:
                    continue
                rem = cm & unknown
                if rem == 0:
                    return None
                if rem.bit_count() == 1:
                    true |= rem
                    changed = True
            unknown = self.allmask & ~(true | false)
            for cm in self.neg:
                if cm & false:
                    continue
                rem = cm & unknown
                if rem == 0:
                    return None
                if rem.bit_count() == 1:
                    false |= rem
                    changed = True
            if true & false:
                return None
            unknown = self.allmask & ~(true | false)
            if self.deg:
                for im in self.inc:
                    blue = (im & false).bit_count()
                    unk = im & unknown
                    unkc = unk.bit_count()
                    # max blue degree
                    bmax = self.deg[0][1]
                    if blue > bmax:
                        return None
                    if blue == bmax and unk:
                        true |= unk
                        changed = True
                    # min blue degree
                    bmin = self.deg[1][0]
                    if blue + unkc < bmin:
                        return None
                    if blue + unkc == bmin and unk:
                        false |= unk
                        changed = True
            if true & false:
                return None
        return true, false

    def choose(self, true, false):
        unknown = self.allmask & ~(true | false)
        if unknown == 0:
            return -1
        best = None
        best_score = -1
        # Score unknown edges by participation in currently tight constraints.
        sample = unknown
        while sample:
            lb = sample & -sample
            e = lb.bit_length() - 1
            score = 0
            for cm in self.pos:
                if lb & cm and not (cm & true):
                    u = (cm & unknown).bit_count()
                    if u <= 4:
                        score += 10 - u
            for cm in self.neg:
                if lb & cm and not (cm & false):
                    u = (cm & unknown).bit_count()
                    if u <= 8:
                        score += 10 - min(u, 9)
            for im in self.inc:
                if lb & im:
                    blue = (im & false).bit_count()
                    unk = (im & unknown).bit_count()
                    if self.deg:
                        score += blue + max(0, self.deg[1][0] - (blue + unk - 1))
            if score > best_score:
                best_score = score
                best = e
            sample ^= lb
        return best

    def search(self, true=0, false=0, depth=0):
        self.nodes += 1
        if self.nodes % 1000 == 0:
            print("nodes", self.nodes, "depth", depth, "assigned", (true | false).bit_count(), "time", round(time.time()-self.start, 2), file=sys.stderr)
        p = self.propagate(true, false)
        if p is None:
            return False, None
        true, false = p
        e = self.choose(true, false)
        if e < 0:
            return True, (true, false)
        bit = 1 << e
        # Try blue first for R(3,k); it tends to expose triangle propagation.
        for val in (0, 1):
            if val:
                sat, sol = self.search(true | bit, false, depth + 1)
            else:
                sat, sol = self.search(true, false | bit, depth + 1)
            if sat:
                return True, sol
        return False, None


def main():
    n, s, t = map(int, sys.argv[1:4])
    sol = Solver(n, s, t)
    sat, model = sol.search()
    print("SAT" if sat else "UNSAT", "nodes", sol.nodes, "time", time.time() - sol.start)


if __name__ == "__main__":
    main()
