公式

C - 権限管理システム / Permission Management System 解説 by admin

Gemini 3.0 Flash (Thinking)

Overview

This is a problem of finding the “minimum privilege” required to access multiple resources. The required privilege for each resource is represented as a bit string, and we compute the minimum bit string that encompasses all of them.

Analysis

1. Understanding the Access Condition

The condition for an employee’s privilege \(K\) to satisfy the required privilege \(S_i\) of resource \(i\) is \(K \mathbin{\&} S_i = S_i\). Looking at this bit by bit, this means “any bit that is 1 in \(S_i\) must also be 1 in \(K\).” Conversely, for bits where \(S_i\) is 0, \(K\) can be either 0 or 1 and still satisfy the condition.

2. Satisfying Multiple Resources Simultaneously

When a single request specifies multiple resources \(\{c_1, c_2, \dots, c_M\}\), the condition must be satisfied for all of them. In other words, “if a certain bit is 1 in any of the specified resources, then that bit must also be 1 in the employee’s privilege \(K\).”

3. Finding the Minimum Value

To “minimize the value when interpreting the bit string as a binary number,” we simply set all non-essential bits to 0. Therefore, the minimum required privilege \(K\) is obtained by taking the bitwise OR of the required privileges \(S_i\) of all specified resources.

Concrete Example

  • Resource 1: 1010
  • Resource 2: 1100 If we want to access both of these:
  • 1st bit: Both are 1, so \(K\) is also 1
  • 2nd bit: Resource 2 is 1, so \(K\) is also 1
  • 3rd bit: Resource 1 is 1, so \(K\) is also 1
  • 4th bit: Both are 0, so \(K\) can be 0 (for minimization) Result: 1110 (This matches the result of 1010 | 1100)

Algorithm

  1. Convert each resource’s required privilege \(S_i\) (a string) to an integer for easier computation and store it in an array.
  2. For each query (request), perform the following:
    • Initialize a variable res_val to \(0\).
    • For each resource number \(c_{j,k}\) included in the request, compute res_val |= S[c_{j,k}] (bitwise OR).
    • Convert the final res_val to a binary string of length \(L\) and output it.

Complexity

  • Time Complexity: \(O(N + \sum M_j + QL)\)
    • Reading and converting resources to integers takes \(O(N)\).
    • The total number of resource lookups and OR operations across all queries is \(\sum M_j\), which is at most \(10^5\) by the constraints.
    • Generating the output strings takes \(O(QL)\).
  • Space Complexity: \(O(N)\)
    • \(O(N)\) memory is used to store the required privileges of the resources.

Implementation Notes

  • Fast I/O: Since \(N\), \(Q\), and \(\sum M_j\) can be as large as \(10^5\), in Python you can reduce execution time by reading all input at once using sys.stdin.read().split(), and by accumulating results in a list and outputting them all at once with join.

  • Binary String Formatting: To convert an integer to a binary string of \(L\) digits (zero-padded), it is convenient to use format(val, '0' + str(L) + 'b') or f-strings.

    Source Code

import sys

def solve():
    """
    権限管理システムの最小権限ビット列を求める問題を解く関数です。
    
    各リソース Si にアクセスするための最小の権限 K は、
    K & Si = Si を満たす必要があります。
    複数のリソースに対してこの条件を満たす最小の K は、
    それらのリソースの必要権限 Si のビットごとの論理和 (OR) です。
    """
    
    # 全ての入力を一度に読み込み、空白で分割してイテレータを作成します。
    # これにより、大量の入力を高速に処理できます。
    try:
        input_data = sys.stdin.read().split()
    except EOFError:
        return
        
    if not input_data:
        return
    
    it = iter(input_data)
    
    # N: リソースの数, L: ビット列の長さ, Q: 依頼の数
    try:
        N = int(next(it))
        L = int(next(it))
        Q = int(next(it))
    except StopIteration:
        return
    
    # 各リソースの必要権限 Si を整数のリストとして格納します。
    # 2進数文字列を整数に変換して保持することで、ビット演算を高速化します。
    S = [0] * N
    for i in range(N):
        try:
            S[i] = int(next(it), 2)
        except StopIteration:
            break
            
    # 出力形式(長さ L の 0 埋め 2 進数文字列)を指定するためのフォーマット文字列を作成します。
    fmt_str = '0' + str(L) + 'b'
    results = []
    
    # 各依頼(クエリ)を順番に処理します。
    for _ in range(Q):
        try:
            # M_j: 依頼に含まれるリソースの数
            M_j = int(next(it))
            res_val = 0
            # 指定されたすべてのリソースの必要権限のビット論理和を計算します。
            for _ in range(M_j):
                # リソース番号は 1-indexed なので、0-indexed に変換します。
                idx = int(next(it)) - 1
                res_val |= S[idx]
            
            # 計算された最小の権限ビット列を、指定されたフォーマットで文字列に変換します。
            results.append(format(res_val, fmt_str))
        except StopIteration:
            break
            
    # 全ての依頼に対する結果を改行区切りで結合し、一度に出力します。
    if results:
        sys.stdout.write('\n'.join(results) + '\n')

if __name__ == '__main__':
    solve()

This editorial was generated by gemini-3-flash-thinking.

投稿日時:
最終更新: