E - 商品の逆元ポイント / Modular Inverse Points of Products 解説 by admin
gemini-3.5-flash-thinkingOverview
This problem asks us to find the modular inverse of the product of item prices. By utilizing the property of modular inverses that “the inverse of a product equals the product of the individual inverses,” we can reformulate the problem in a simpler way. We precompute the modular inverse of each item’s price, then reduce the problem to efficiently computing the sum of all products formed by choosing \(K\) of these inverses, using dynamic programming (DP).
Analysis
1. Naive Approach and Its Limitations
There are \(\binom{N}{K}\) ways to choose items. For example, when \(N = 5000, K = 2500\), the number of combinations becomes astronomically large. Computing the product \(P\) and its inverse for every combination directly would result in a Time Limit Exceeded (TLE) verdict.
2. Reformulation Using Properties of Modular Inverses
Modular inverses have the following useful property. When the product \(P = A_{i_1} A_{i_2} \cdots A_{i_K}\) is not a multiple of \(M\), the modular inverse of \(P\) modulo \(M\) can be decomposed as follows:
\[ P^{-1} \equiv (A_{i_1} A_{i_2} \cdots A_{i_K})^{-1} \equiv A_{i_1}^{-1} A_{i_2}^{-1} \cdots A_{i_K}^{-1} \pmod M \]
In other words, “the inverse of the product of the selected item prices” equals “the product of the inverses of the selected item prices.” With this insight, if we precompute the modular inverse of each item’s price, the problem simplifies to “computing the sum of all products formed by choosing \(K\) elements from the set of inverses” (i.e., computing the elementary symmetric polynomial).
3. Handling Items Whose Price is a Multiple of \(M\)
If a price \(A_i\) is a multiple of \(M\), its modular inverse does not exist. Furthermore, if even one such item is selected, the overall product \(P\) becomes a multiple of \(M\), and the earned points become \(0\). Therefore, items where \(A_i \equiv 0 \pmod M\) can be excluded from the start.
After exclusion, if the number of remaining items (those with existing inverses) is less than \(K\), then any selection will necessarily include a multiple of \(M\), so the total points is \(0\).
Algorithm
We find the solution using the following steps:
Preprocessing (Computing Inverses) For each item \(i\), only if \(A_i \pmod M \neq 0\), compute the inverse \(B_j \equiv A_i^{M-2} \pmod M\) using Fermat’s Little Theorem, and append it to array \(B\).
Checking the Number of Elements If the number of elements in array \(B\) is less than \(K\), the answer is \(0\).
Computing the Sum of Products Using Dynamic Programming (DP) Use DP to compute the sum of all products formed by choosing \(K\) elements from array \(B\).
dp[j]: the sum of all products when choosing \(j\) elements from those seen so far- Initial values:
dp[0] = 1, all others are0 - Transition: For each element \(b\) in array \(B\),
dp[j] = (dp[j] + dp[j-1] * b) % M(※ To avoid selecting the same element more than once, updatejin reverse order from \(K\) down to \(1\))
Output The final answer is
dp[K].
Complexity
Time Complexity: \(O(N \log M + NK)\)
- Computing the inverse of each element takes \(O(\log M)\) using fast exponentiation (the
powfunction). Doing this up to \(N\) times gives \(O(N \log M)\). - The DP transition is a double loop over the number of elements (at most \(N\)) \(\times\) the number chosen \(K\), giving \(O(NK)\).
- With \(N, K \le 5000\), the total number of operations is approximately \(2.5 \times 10^7\), which comfortably fits within the time limit.
- Computing the inverse of each element takes \(O(\log M)\) using fast exponentiation (the
Space Complexity: \(O(N + K)\)
- The array \(B\) storing inverses has size at most \(O(N)\), and the DP table has size \(O(K)\), making this very memory-efficient.
Implementation Notes
Fast Inverse Computation: In Python, using
pow(base, exp, mod)internally applies fast exponentiation, efficiently computing \(base^{exp} \pmod{mod}\).DP Optimization with a 1D Array: During the DP transition, by iterating the loop in reverse order (decrementing from
limitto1), we avoid overwriting old information and can complete the transition using only a 1D array. This reduces the space complexity from \(O(NK)\) to \(O(K)\).Source Code
import sys
def solve():
input_data = sys.stdin.read().split()
if not input_data:
return
N = int(input_data[0])
K = int(input_data[1])
M = int(input_data[2])
A = [int(x) for x in input_data[3:]]
B = []
for a in A:
val = a % M
if val != 0:
B.append(pow(val, M - 2, M))
if len(B) < K:
print(0)
return
dp = [0] * (K + 1)
dp[0] = 1
count = 0
for b in B:
count += 1
limit = min(K, count)
for j in range(limit, 0, -1):
dp[j] = (dp[j] + dp[j-1] * b) % M
print(dp[K])
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3.5-flash-thinking.
投稿日時:
最終更新: