import sys # sys.setrecursionlimit(1000005) # sys.set_int_max_str_digits(200005) int1 = lambda x: int(x)-1 pDB = lambda *x: print(*x, end="\n", file=sys.stderr) p2D = lambda x: print(*x, sep="\n", end="\n\n", file=sys.stderr) def II(): return int(sys.stdin.readline()) def LI(): return list(map(int, sys.stdin.readline().split())) def LLI(rows_number): return [LI() for _ in range(rows_number)] def LI1(): return list(map(int1, sys.stdin.readline().split())) def LLI1(rows_number): return [LI1() for _ in range(rows_number)] def SI(): return sys.stdin.readline().rstrip() dij = [(0, 1), (-1, 0), (0, -1), (1, 0)] # dij = [(0, 1), (-1, 0), (0, -1), (1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)] # inf = -1-(-1 << 31) inf = -1-(-1 << 62) # md = 10**9+7 md = 998244353 class StronglyConnectedComponents: def __init__(self, n): self.n = n self.graph = [[] for _ in range(n)] self.ord = [-1]*n self.low = [-1]*n self.labels = [-1]*n self.lb_cnt = 0 def add_edge(self, v, nxt_v): self.graph[v].append(nxt_v) def build(self): k = 0 idxs = [0]*self.n for v in range(self.n): if self.ord[v] == -1: k = self.dfs(v, k, idxs) self.labels = [self.lb_cnt-lb-1 for lb in self.labels] def dfs(self, root, k, idxs): dfs_stack = [root] scc_stack = [] while dfs_stack: v = dfs_stack[-1] if v < 0: v = ~v prv_v = dfs_stack[-2] self.low[prv_v] = min(self.low[prv_v], self.low[v]) dfs_stack.pop() continue idx = idxs[v] if self.ord[v] == -1: self.ord[v] = self.low[v] = k k += 1 scc_stack.append(v) if idx < len(self.graph[v]): nxt_v = self.graph[v][idx] idxs[v] += 1 if self.ord[nxt_v] == -1: dfs_stack.append(~nxt_v) dfs_stack.append(nxt_v) elif self.labels[nxt_v] == -1: self.low[v] = min(self.low[v], self.ord[nxt_v]) else: if self.ord[v] == self.low[v]: while True: prv_v = scc_stack.pop() self.labels[prv_v] = self.lb_cnt if prv_v == v: break self.lb_cnt += 1 dfs_stack.pop() return k def construct_dag(self): self.dag = [[] for i in range(self.lb_cnt)] self.groups = [[] for i in range(self.lb_cnt)] for v, lb in enumerate(self.labels): for nxt_v in self.graph[v]: nxt_lb = self.labels[nxt_v] if lb == nxt_lb: continue self.dag[lb].append(nxt_lb) self.groups[lb].append(v) return self.dag, self.groups class TwoSAT: # nは2倍化する前の頂点数 def __init__(self, n): self.n = n self.scc = StronglyConnectedComponents(2*n) self.ans = [False]*self.n # (uがf)または(vがg) u,v頂点、f,g真偽 def add_clause(self, u, f, v, g): self.scc.add_edge(2*u+int(not f), 2*v+int(g)) self.scc.add_edge(2*v+int(not g), 2*u+int(f)) def satisfy(self): self.scc.build() for i in range(self.n): if self.scc.labels[2*i] == self.scc.labels[2*i+1]: return False self.ans[i] = self.scc.labels[2*i] < self.scc.labels[2*i+1] return True def answer(self): return self.ans class Sieve: def __init__(self, n): self.plist = [2] min_prime_factor = [2, 0]*(n//2+1) for x in range(3, n+1, 2): if min_prime_factor[x] == 0: min_prime_factor[x] = x self.plist.append(x) if x**2 > n: continue for y in range(x**2, n+1, 2*x): if min_prime_factor[y] == 0: min_prime_factor[y] = x self.min_prime_factor = min_prime_factor def isprime(self, x): return self.min_prime_factor[x] == x def pf(self, x): pp, ee = [], [] while x > 1: mpf = self.min_prime_factor[x] if pp and mpf == pp[-1]: ee[-1] += 1 else: pp.append(mpf) ee.append(1) x //= mpf return pp, ee # unsorted def factor(self, a): ff = [1] pp, ee = self.pf(a) for p, e in zip(pp, ee): ff, gg = [], ff w = p for _ in range(e): for f in gg: ff.append(f*w) w *= p ff += gg return ff sv=Sieve(10001000) n=II() ab=[SI().split() for _ in range(n)] ts=TwoSAT(n) for u,(a,b) in enumerate(ab): cnt=0 for f in range(2): x=int(a+b) if sv.isprime(x): cnt+=1 ts.add_clause(u,f,u,f^1) a,b=b,a if cnt==2: # print(u,a,b) print("No") exit() for u in range(n): a,b=ab[u] for v in range(u): s,t=ab[v] for f in range(2): for g in range(2): x=int(a+t) y=int(s+b) if sv.isprime(x) or sv.isprime(y): ts.add_clause(u,f,v,g^1) s,t=t,s a,b=b,a print("Yes" if ts.satisfy() else "No")