D - 工場の生産量 / Factory Production Volume 解説 by admin
GPT 5.2 HighOverview
Using the product of the original array \(P_1,\dots,P_N\) modulo \(M\) (a prime) as a base, we efficiently compute the product \(\bmod M\) when exactly one element is replaced by \(V\) for each query.
Analysis
If we naively compute for each query: - Calculate the product \(P_1\times\cdots\times P_N\) from scratch each time
this costs \(O(N)\) per query, resulting in \(O(NQ)\) overall, which is far too slow for \(N,Q\le 2\times 10^5\).
The key observation is as follows:
- The product after replacement can be written as
$\((P_1\cdots P_N)\times P_{X}^{-1}\times V \pmod M\)\( (when \)P_X \not\equiv 0 \pmod M$). - Since \(M\) is prime, for any \(a\not\equiv 0\pmod M\), the modular inverse \(a^{-1}\) always exists and can be computed by Fermat’s little theorem:
$\(a^{-1}\equiv a^{M-2}\pmod M\)$ - However, if any \(P_i \equiv 0 \pmod M\) is present, the inverse does not exist, and the product tends to become 0.
Therefore, we can handle this cleanly by counting “the number of \(P_i \bmod M\) that are 0” and doing case analysis.
Specifically, letting \(P_i' = P_i \bmod M\): - If there are 2 or more zeros, then even after replacing one of them, at least one zero remains, so the product is always 0. - If there is exactly 1 zero, the product can become non-zero only when we replace the element at that zero position. - If there are 0 zeros, we can update in one step using the modular inverse.
With this approach, each query can be processed in \(O(1)\) (with inverse computation done in preprocessing).
Algorithm
- Read input and compute \(P_i' = P_i \bmod M\).
- Precompute the following:
zero_cnt: the number of elements where \(P_i'=0\)prod_nonzero: the product of all elements where \(P_i'\ne 0\) (modulo \(M\))
- Case analysis:
zero_cnt >= 2
The answer is always 0 for any query.zero_cnt == 1
When a query replaces position \(x\) with \(v\), let \(v' = v \bmod M\):- If the original \(P_x'==0\) (replacing the zero position), the answer is
$\(\text{prod\_nonzero} \times v' \bmod M\)\( (of course, if \)v’=0$ then the answer is 0) - If replacing any other position, the zero remains, so the answer is 0.
- If the original \(P_x'==0\) (replacing the zero position), the answer is
zero_cnt == 0
Prepare the total producttotal = prod_nonzero, and for each \(i\), precompute the inverse
$\(\text{inv}[i] = (P_i')^{M-2}\bmod M\)\( For a query \)(x,v)$:- If \(v'=0\), the answer is 0
- Otherwise:
$\(\text{ans} = \text{total} \times \text{inv}[x] \times v' \bmod M\)$
Simple Example
\(M=7\), \(P'=[2,0,3]\) (1 zero), prod_nonzero = 2\times 3=6.
- Replacing \(x=2\) (the zero position) with \(v=5\): the answer is \(6\times 5=30\equiv 2\pmod 7\).
- Replacing \(x=1\) with anything: since the zero at position 2 remains, the answer is 0.
Complexity
- Time complexity:
Preprocessing computes \(N\) modular inverses in \(O(N\log M)\), and each query is \(O(1)\) for a total of \(O(Q)\).
Overall: \(O(N\log M + Q)\) - Space complexity:
Storing arrays (\(P'\) and inverses): \(O(N)\)
Implementation Notes
Always take \(P_i\) and \(V_j\) modulo \(M\) first before processing (zero checks are also done after taking \(\bmod M\)).
Modular inverses are computed using
pow(a, M-2, M), leveraging the fact that \(M\) is prime.When \(P_i'\equiv 0\), the inverse does not exist, so the case analysis using
zero_cntis essential.Since \(N,Q\) can be large, using fast I/O (such as
sys.stdin.buffer.read()) helps ensure stable performance.Source Code
import sys
def read_ints():
data = sys.stdin.buffer.read()
n = len(data)
i = 0
while i < n:
while i < n and data[i] <= 32:
i += 1
if i >= n:
break
x = 0
while i < n and data[i] > 32:
x = x * 10 + (data[i] - 48)
i += 1
yield x
it = read_ints()
N = next(it)
Q = next(it)
M = next(it)
P = [next(it) for _ in range(N)]
Pmod = [p % M for p in P]
zero_cnt = 0
prod_nonzero = 1
for a in Pmod:
if a == 0:
zero_cnt += 1
else:
prod_nonzero = (prod_nonzero * a) % M
inv = None
total = None
if zero_cnt == 0:
total = prod_nonzero
inv = [0] * N
exp = M - 2
for i, a in enumerate(Pmod):
inv[i] = pow(a, exp, M)
out = []
for _ in range(Q):
x = next(it) - 1
v = next(it)
vx = v % M
if zero_cnt >= 2:
out.append("0")
continue
if zero_cnt == 1:
if Pmod[x] == 0:
if vx == 0:
out.append("0")
else:
out.append(str((prod_nonzero * vx) % M))
else:
out.append("0")
continue
# zero_cnt == 0
if vx == 0:
out.append("0")
else:
ans = total * inv[x] % M
ans = ans * vx % M
out.append(str(ans))
sys.stdout.write("\n".join(out))
This editorial was generated by gpt-5.2-high.
投稿日時:
最終更新: