// Package q1622 implements a solution for https://leetcode.com/problems/fancy-sequence/ // ref: https://en.wikipedia.org/wiki/Fermat%27s_little_theorem package q1622 const MOD int = 1e9 + 7 type Fancy struct { numbers []int states []fancyState // this can be optimized out add, mul, inv int } type fancyState struct{ add, inv int } func Constructor() Fancy { return Fancy{ numbers: make([]int, 0, 128), states: make([]fancyState, 0, 128), mul: 1, inv: 1, } } // findInv calculates num^(MOD-2), which is the inverse of num under mod MOD // when MOD is a prime number. `inv(num) * num % MOD == 1`. func findInv(num int) int { pow := MOD - 2 ret := 1 cur := num % MOD for i := 1; 1<<(i-1) <= pow; i++ { if (pow>>(i-1))&1 == 1 { ret = (ret * cur) % MOD } cur = cur * cur % MOD } return ret } func (f *Fancy) Append(val int) { f.numbers = append(f.numbers, val) f.states = append(f.states, fancyState{add: f.add, inv: f.inv}) } func (f *Fancy) AddAll(inc int) { f.add = (f.add + inc) % MOD } func (f *Fancy) MultAll(m int) { f.mul = f.mul * m % MOD f.add = f.add * m % MOD f.inv = findInv(f.mul) } func (f *Fancy) GetIndex(idx int) int { if idx >= len(f.numbers) { return -1 } num := f.numbers[idx] * f.mul % MOD * f.states[idx].inv % MOD savedAdd := f.states[idx].add * f.mul % MOD * f.states[idx].inv % MOD return (num + MOD + f.add - savedAdd) % MOD } /** * Your Fancy object will be instantiated and called as such: * obj := Constructor(); * obj.Append(val); * obj.AddAll(inc); * obj.MultAll(m); * param_4 := obj.GetIndex(idx); */