結果

問題 No.2121 帰属関係と充足可能性
ユーザー qwewe
提出日時 2025-05-14 13:19:12
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 303 ms / 2,000 ms
コード長 8,467 bytes
コンパイル時間 428 ms
コンパイル使用メモリ 83,028 KB
実行使用メモリ 129,756 KB
最終ジャッジ日時 2025-05-14 13:20:03
合計ジャッジ時間 4,312 ms
ジャッジサーバーID
(参考情報)
judge2 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 49
権限があれば一括ダウンロードができます

ソースコード

diff #

import sys

# Increase recursion depth if necessary, though the iterative generation should avoid deep recursion.
# sys.setrecursionlimit(2000) 

def solve():
    N = int(sys.stdin.readline())
    A = list(map(int, sys.stdin.readline().split()))
    A0, A1, A2, A3, A4, A5 = A

    # Handle N=0 case: V_0 is the empty set, so no elements m_0, m_1, m_2 exist.
    if N == 0:
        print("NO")
        return

    # Check for conditions that violate the Axiom of Regularity (no set contains itself).
    # In the context of Von Neumann hierarchy V_N, sets are well-founded, so x \in x is impossible.
    # Condition 2: m_{A1} \in m_{A2}. If A1 == A2, this becomes m_{A1} \in m_{A1}, which is impossible.
    # Condition 3: m_{A3} \in m_{A2}. If A3 == A2, this becomes m_{A2} \in m_{A2} (since m_{A3}=m_{A2}), impossible.
    # Condition 4: m_{A4} \in m_{A2}. If A4 == A2, this becomes m_{A2} \in m_{A2}, impossible.
    # Condition 5: m_{A5} \in m_{A0}. If A5 == A0, this becomes m_{A0} \in m_{A0}, impossible.
    if A5 == A0 or A1 == A2 or A3 == A2 or A4 == A2:
        print("NO")
        return

    # Generate the hierarchy of sets V_k up to V_N.
    # We assign a unique integer ID to each distinct set encountered.
    
    # `all_sets` list stores the canonical representation (sorted tuple of element IDs) for each set ID.
    # ID 0 is reserved for the empty set.
    all_sets = [()] 
    # `set_to_id` dictionary maps canonical representation (tuple) to the assigned set ID.
    set_to_id = {(): 0}
    next_id = 1
    
    # `V_k_ids` list of lists stores the IDs of sets belonging to each V_k.
    V_k_ids = [[] for _ in range(N + 1)]
    
    # V_0 is the empty set, has no elements. Its list of IDs is empty.
    V_k_ids[0] = [] 
    
    # V_1 = {emptyset}. The empty set has ID 0.
    empty_set_id = 0 
    if N >= 1:
        V_k_ids[1] = [empty_set_id]

    # Generate V_k for k=1..N iteratively.
    # V_k is the power set of V_{k-1}.
    for k in range(1, N + 1):
        
        # Get the list of IDs of elements in V_{k-1}
        elements_of_V_k_minus_1_ids = V_k_ids[k-1]
        num_elements_V_k_minus_1 = len(elements_of_V_k_minus_1_ids)
        
        # Store IDs of sets that constitute V_k
        current_V_k_ids = []

        # Iterate through all possible subsets of V_{k-1} using bitmasks.
        # Each integer `i` from 0 to 2^|V_{k-1}| - 1 represents a subset.
        limit = 1 << num_elements_V_k_minus_1
        
        for i in range(limit): 
            # Construct the current subset based on the bits of `i`.
            subset_element_ids = []
            for j in range(num_elements_V_k_minus_1):
                if (i >> j) & 1:
                    # If j-th bit is set, include the j-th element of V_{k-1} in the subset.
                    subset_element_ids.append(elements_of_V_k_minus_1_ids[j])
            
            # Use a sorted tuple of element IDs as the canonical representation for the set.
            subset_element_ids.sort() 
            canon_rep = tuple(subset_element_ids)
            
            set_id = -1
            # Check if this set structure has been seen before.
            if canon_rep in set_to_id:
                set_id = set_to_id[canon_rep]
            else:
                # Assign a new ID if it's a new set structure.
                set_id = next_id
                set_to_id[canon_rep] = set_id
                all_sets.append(canon_rep)
                next_id += 1
            
            # Add the ID of this set to the list for V_k.
            current_V_k_ids.append(set_id)

        # Store the generated IDs for V_k. Sorting is optional but helps consistency.
        V_k_ids[k] = sorted(current_V_k_ids)

    # Finished generating sets up to V_N.

    # Get the list of IDs for elements in V_N.
    V_N_element_ids = V_k_ids[N]
    
    # It's possible V_N is empty only if N=0, which is handled already.
    # If N > 0, V_N always contains at least the empty set.
    
    # Create a set of IDs for elements in V_{N-1} for efficient lookups.
    ids_V_N_minus_1_set = set(V_k_ids[N-1])

    # Determine which variables (m_0, m_1, m_2) MUST be assigned values from V_{N-1}.
    # This is required by the membership conditions: if `m_X \in m_Y`, then `m_X` must be an element of `V_{N-1}`
    # because `m_Y \in V_N` implies `m_Y \subseteq V_{N-1}`.
    restricted_vars_flags = [False, False, False]
    
    # Condition 2: m_{A1} \in m_{A2}. Implies m_{A1} must be a set from V_{N-1}. The variable m_{A1} is restricted.
    restricted_vars_flags[A1] = True
    # Condition 3: m_{A3} \in m_{A2}. Implies m_{A3} must be a set from V_{N-1}. The variable m_{A3} is restricted.
    restricted_vars_flags[A3] = True
    # Condition 4: m_{A4} \in m_{A2}. Implies m_{A4} must be a set from V_{N-1}. The variable m_{A4} is restricted.
    restricted_vars_flags[A4] = True
    # Condition 5: m_{A5} \in m_{A0}. Implies m_{A5} must be a set from V_{N-1}. The variable m_{A5} is restricted.
    restricted_vars_flags[A5] = True

    # Define the possible choices (domain) for each variable m_0, m_1, m_2.
    # Initially, assume all elements of V_N are possible choices.
    choice_sets = [list(V_N_element_ids) for _ in range(3)] 
    
    # Apply restrictions based on `restricted_vars_flags`.
    for i in range(3):
      if restricted_vars_flags[i]:
          # If m_i is restricted, filter its choice set to include only IDs that are also in V_{N-1}.
          choice_sets[i] = [id_val for id_val in choice_sets[i] if id_val in ids_V_N_minus_1_set]

    # Precompute Python set objects for each set ID for faster subset and membership checks.
    # `all_sets[i]` is a tuple representing the elements (by ID) of the set with ID `i`.
    # `all_sets_as_python_sets[i]` is the corresponding Python set object.
    all_sets_as_python_sets = { i : set(all_sets[i]) for i in range(len(all_sets)) }

    # If any choice set becomes empty after applying restrictions, no solution is possible.
    if not choice_sets[0] or not choice_sets[1] or not choice_sets[2]:
         print("NO")
         return

    # Iterate through the restricted search space for assignments (id_0, id_1, id_2).
    # This significantly reduces the number of checks compared to |V_N|^3 for large N.
    for id_0 in choice_sets[0]:
        for id_1 in choice_sets[1]:
            for id_2 in choice_sets[2]:
                
                # Current assignment: m_0 has ID id_0, m_1 has ID id_1, m_2 has ID id_2.
                ids = [id_0, id_1, id_2]
                
                # Map the A_k indices to the actual IDs based on the current assignment.
                id_A0 = ids[A0]
                id_A1 = ids[A1]
                id_A2 = ids[A2]
                id_A3 = ids[A3]
                id_A4 = ids[A4]
                id_A5 = ids[A5]
                
                # Retrieve the precomputed Python set objects for the relevant IDs.
                set_A0 = all_sets_as_python_sets[id_A0]
                set_A1 = all_sets_as_python_sets[id_A1]
                set_A2 = all_sets_as_python_sets[id_A2]

                # Check the 5 conditions of the formula:

                # Condition 1: m_{A0} \subseteq m_{A1}
                # Check if the set represented by id_A0 is a subset of the set represented by id_A1.
                if not set_A0.issubset(set_A1): 
                    continue # If condition fails, try next assignment.

                # Condition 2: m_{A1} \in m_{A2} 
                # Check if the ID representing set m_{A1} (which is id_A1) is an element of the set m_{A2}.
                # `set_A2` contains the IDs of elements constituting the set m_{A2}.
                if id_A1 not in set_A2: 
                    continue 

                # Condition 3: m_{A3} \in m_{A2}
                if id_A3 not in set_A2: 
                    continue

                # Condition 4: m_{A4} \in m_{A2}
                if id_A4 not in set_A2: 
                    continue

                # Condition 5: m_{A5} \in m_{A0}
                if id_A5 not in set_A0: # `set_A0` contains IDs of elements of m_{A0}.
                    continue
                
                # If all 5 conditions are satisfied for this triple (id_0, id_1, id_2).
                print("YES")
                return # Found a satisfying assignment, exit.

    # If the loops complete without finding any satisfying assignment.
    print("NO")

# Execute the solver function.
solve()
0