请你实现三个 API append,addAll 和 multAll 来实现奇妙序列。
请实现 Fancy 类 :
Fancy() 初始化一个空序列对象。 void append(val) 将整数 val 添加在序列末尾。 void addAll(inc) 将所有序列中的现有数值都增加 inc 。 void multAll(m) 将序列中的所有现有数值都乘以整数 m 。 int getIndex(idx) 得到下标为 idx 处的数值(下标从 0 开始),并将结果对 109 + 7 取余。如果下标大于等于序列的长度,请返回 -1 。
示例:
输入: ["Fancy", "append", "addAll", "append", "multAll", "getIndex", "addAll", "append", "multAll", "getIndex", "getIndex", "getIndex"] [[], [2], [3], [7], [2], [0], [3], [10], [2], [0], [1], [2]] 输出: [null, null, null, null, null, 10, null, null, null, 26, 34, 20]
解释: Fancy fancy = new Fancy(); fancy.append(2); // 奇妙序列:[2] fancy.addAll(3); // 奇妙序列:[2+3] -> [5] fancy.append(7); // 奇妙序列:[5, 7] fancy.multAll(2); // 奇妙序列:[5*2, 7*2] -> [10, 14] fancy.getIndex(0); // 返回 10 fancy.addAll(3); // 奇妙序列:[10+3, 14+3] -> [13, 17] fancy.append(10); // 奇妙序列:[13, 17, 10] fancy.multAll(2); // 奇妙序列:[13*2, 17*2, 10*2] -> [26, 34, 20] fancy.getIndex(0); // 返回 26 fancy.getIndex(1); // 返回 34 fancy.getIndex(2); // 返回 20
提示:
1 <= val, inc, m <= 100 0 <= idx <= 105 总共最多会有 105 次对 append,addAll,multAll 和 getIndex 的调用。
思路:我们定义两个变量分别记录加法和乘法的执行历史,在每添加一个新的元素时,之前的加法和乘法操作都不影响该元素,因此我们可以通过减法和除法来去掉,在查询该元素时通过记录的add和mul变可以求出该元素的实际值。
注意:由于余数的存在,除法要通过逆元实现!
class Fancy { private long add, mul; private List<Integer> list; private static final int mod = 1000000007; public Fancy() { add = 0; mul = 1; list = new ArrayList<>(); } public void append(int val) { val = (int) ((val - add + mod) % mod); val = (int) (((long) val * q(mul, mod - 2)) % mod); list.add(val); } public void addAll(int inc) { add = (add + inc) % mod; } public void multAll(int m) { add = add * m % mod; mul = mul * m % mod; } public int getIndex(int idx) { if (idx >= list.size()) return -1; return (int) ((list.get(idx) * mul + add) % mod); } private long q(long x, int y) { long res = 1; while (y > 0) { if (y % 2 != 0) res = res * x % mod; x = x * x % mod; y /= 2; } return res; } }