|
| 1 | +# [Problem 1622: Fancy Sequence](https://leetcode.com/problems/fancy-sequence/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | +We need to support append, addAll, multAll, and getIndex efficiently. Naively applying addAll or multAll to every element is O(n) per operation and too slow (up to 1e5 ops). The operations are linear transforms on values: each element's value is transformed by x -> x * m + a for sequences of multiplies and adds. That suggests keeping a global linear transformation state (mul, add) that represents how to convert a stored "base" value to its current value. When appending, we can store a normalized base so that current value after the global transform equals the appended value. When retrieving, apply the global transform to the stored base. That avoids touching all stored elements on addAll/multAll. |
| 5 | + |
| 6 | +I recall two equivalent ways: |
| 7 | +- Store for each appended element the global (mul, add) at its append time and the original value, then invert the per-append transform when computing current value. |
| 8 | +- Or normalize the appended value at append-time by applying the inverse of current global mul/add, i.e., store base = (val - add) * inv(mul) so that current = base * mul + add. |
| 9 | + |
| 10 | +I'll use the second (store normalized base) because it's simpler: only need a global mul and add, and per-append compute one modular inverse. |
| 11 | + |
| 12 | +Careful: operations are modulo MOD = 10^9+7. The multiplicative inverse exists because m in operations is between 1 and 100 and MOD is prime, so mul (product of ms modulo MOD) will never be 0 modulo MOD (can't get a factor of MOD from small integers). Use pow(mul, MOD-2, MOD) for inverse. |
| 13 | + |
| 14 | +## Refining the problem, round 2 thoughts |
| 15 | +Refinements and edge cases: |
| 16 | +- getIndex must return -1 if idx out of bounds. |
| 17 | +- Maintain arr of stored normalized bases (one per append). For append(val): compute base = (val - add) * inv(mul) mod MOD and append. |
| 18 | +- For addAll(inc): update add = (add + inc) % MOD. |
| 19 | +- For multAll(m): update mul = mul * m % MOD and add = add * m % MOD (since (x * mul + add) * m = x * (mul*m) + add*m). |
| 20 | +- For getIndex(idx): compute (base * mul + add) % MOD. |
| 21 | +- Need to handle negative (val - add) with modulo. |
| 22 | +- Complexity: each operation O(1) except append does modular inverse with pow (O(log MOD) ~ 30), which is fine for <=1e5 operations. |
| 23 | + |
| 24 | +Alternative approach: store (value, mul_at_append, add_at_append) and compute factor = current_mul * inv(mul_at_append) to reconstruct. Complexity similar. |
| 25 | + |
| 26 | +Now implement the class with Python, using pow for modular inverse. |
| 27 | + |
| 28 | +## Attempted solution(s) |
| 29 | +```python |
| 30 | +MOD = 10**9 + 7 |
| 31 | + |
| 32 | +class Fancy: |
| 33 | + def __init__(self): |
| 34 | + # stores normalized base values for each appended element |
| 35 | + self.arr = [] |
| 36 | + # global transformation: current_value = base * mul + add (mod MOD) |
| 37 | + self.mul = 1 |
| 38 | + self.add = 0 |
| 39 | + |
| 40 | + def append(self, val: int) -> None: |
| 41 | + # store base such that base * mul + add == val (mod MOD) |
| 42 | + # base = (val - add) * inv(mul) mod MOD |
| 43 | + base = (val - self.add) % MOD |
| 44 | + inv_mul = pow(self.mul, MOD - 2, MOD) |
| 45 | + base = (base * inv_mul) % MOD |
| 46 | + self.arr.append(base) |
| 47 | + |
| 48 | + def addAll(self, inc: int) -> None: |
| 49 | + self.add = (self.add + inc) % MOD |
| 50 | + |
| 51 | + def multAll(self, m: int) -> None: |
| 52 | + self.mul = (self.mul * m) % MOD |
| 53 | + self.add = (self.add * m) % MOD |
| 54 | + |
| 55 | + def getIndex(self, idx: int) -> int: |
| 56 | + if idx < 0 or idx >= len(self.arr): |
| 57 | + return -1 |
| 58 | + base = self.arr[idx] |
| 59 | + return (base * self.mul + self.add) % MOD |
| 60 | +``` |
| 61 | +- Notes: |
| 62 | + - Approach: normalize stored values on append so that no per-element updates are necessary on addAll/multAll. Maintain global linear transform (mul, add). |
| 63 | + - Time complexity: append is O(log MOD) due to modular inverse pow (≈ O(30) operations), addAll and multAll are O(1), getIndex is O(1). |
| 64 | + - Space complexity: O(n) where n is the number of appended elements (stored normalized bases). |
| 65 | + - Implementation details: use pow(self.mul, MOD-2, MOD) to compute modular inverse. Ensure subtraction uses modulo to avoid negatives. |
0 commit comments