Fancy Sequence
HardUpdated: Aug 2, 2025
Practice on:
Problem
Write an API that generates fancy sequences using the append, addAll, and multAll operations.
Implement the Fancy class:
Fancy()Initializes the object with an empty sequence.void append(val)Appends an integervalto the end of the sequence.void addAll(inc)Increments all existing values in the sequence by an integerinc.void multAll(m)Multiplies all existing values in the sequence by an integerm.int getIndex(idx)Gets the current value at indexidx(0-indexed) of the sequence modulo109 + 7. If the index is greater or equal than the length of the sequence, return-1.
Examples
Example 1:
**Input**
["Fancy", "append", "addAll", "append", "multAll", "getIndex", "addAll", "append", "multAll", "getIndex", "getIndex", "getIndex"]
[[], [2], [3], [7], [2], [0], [3], [10], [2], [0], [1], [2]]
**Output**
[null, null, null, null, null, 10, null, null, null, 26, 34, 20]
**Explanation**
Fancy fancy = new Fancy();
fancy.append(2); // fancy sequence: [2]
fancy.addAll(3); // fancy sequence: [2+3] -> [5]
fancy.append(7); // fancy sequence: [5, 7]
fancy.multAll(2); // fancy sequence: [5*2, 7*2] -> [10, 14]
fancy.getIndex(0); // return 10
fancy.addAll(3); // fancy sequence: [10+3, 14+3] -> [13, 17]
fancy.append(10); // fancy sequence: [13, 17, 10]
fancy.multAll(2); // fancy sequence: [13*2, 17*2, 10*2] -> [26, 34, 20]
fancy.getIndex(0); // return 26
fancy.getIndex(1); // return 34
fancy.getIndex(2); // return 20
Solution
Method 1 - Using List
The problem involves creating and maintaining a sequence with operations (append, addAll, and multAll) that modify the entire sequence efficiently. Directly applying the operations on all elements every time would result in a poor time complexity when the sequence becomes large. To optimise this process:
Key Observations
- Tracking Operations:
- Instead of modifying every element for each operation, maintain values
addandmultthat track the cumulative additions and multiplications applied to all elements.
- Instead of modifying every element for each operation, maintain values
- Delayed Evaluation:
- When
getIndex(idx)is called, compute the value at the specific index lazily by applying the stored operations.
- When
- Modulo (
10^9 + 7):- Since operations may result in large numbers, ensure all calculations are done modulo
10^9 + 7.
- Since operations may result in large numbers, ensure all calculations are done modulo
Approach
- Use a list
seqto store the appended values. - Maintain two variables:
addfor cumulative addition.multfor cumulative multiplication (starting with 1).
- Implement the methods as follows:
append(val): Append thevaladjusted for the currentmultandadd.addAll(inc): Increment theaddvariable.multAll(m): Updatemult, and adjust theaddbased on the multiplication.getIndex(idx): Retrieve the value atidxusing the stored operations, modulo10^9 + 7.
Code
Java
class Fancy {
private ArrayList<Long> seq;
private long add;
private long mult;
private final int MOD = 1000000007;
public Fancy() {
seq = new ArrayList<>();
add = 0;
mult = 1;
}
public void append(int val) {
seq.add(((val - add + MOD) * modInverse(mult)) % MOD);
}
public void addAll(int inc) {
add = (add + inc) % MOD;
}
public void multAll(int m) {
mult = (mult * m) % MOD;
add = (add * m) % MOD;
}
public int getIndex(int idx) {
if (idx >= seq.size()) return -1;
long ans = (((seq.get(idx) * mult) % MOD) + add) % MOD;
return (int) ans;
}
// Helper function to compute modular inverse using Fermat's Little Theorem
private long modInverse(long x) {
return pow(x, MOD - 2);
}
private long pow(long x, int y) {
long res = 1;
while (y > 0) {
if ((y & 1) == 1) res = (res * x) % MOD;
x = (x * x) % MOD;
y >>= 1;
}
return res;
}
}
Python
class Fancy:
def __init__(self) -> None:
self.seq: List[int] = []
self.add: int = 0
self.mult: int = 1
self.MOD = 10**9 + 7
def append(self, val: int) -> None:
self.seq.append((val - self.add + self.MOD) * self._mod_inverse(self.mult) % self.MOD)
def addAll(self, inc: int) -> None:
self.add = (self.add + inc) % self.MOD
def multAll(self, m: int) -> None:
self.mult = (self.mult * m) % self.MOD
self.add = (self.add * m) % self.MOD
def getIndex(self, idx: int) -> int:
if idx >= len(self.seq):
return -1
ans = (self.seq[idx] * self.mult % self.MOD + self.add) % self.MOD
return ans
def _mod_inverse(self, x: int) -> int:
return self._pow(x, self.MOD - 2)
def _pow(self, x: int, y: int) -> int:
res = 1
while y > 0:
if y & 1:
res = res * x % self.MOD
x = x * x % self.MOD
y >>= 1
return res
Complexity
- ⏰ Time complexity:
O(1)for each operation - 🧺 Space complexity:
O(n)wherenis the number of appended elements in the sequence.