1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
package cal
import ( "math" "sort" )
type Ugly struct { base []int bmul int cbase [][]int ranks [][]int }
func NewUgly(base []int) *Ugly { sort.Ints(base) u := &Ugly{ base: base, bmul: mul(base), } u.calNext() return u }
func (u *Ugly) Get(n int) int { for sumLen(u.ranks) < n { u.calNext() } sl := 0 ret := 0 for i := range u.ranks { li := len(u.ranks[i]) if sl+li >= n { ret = u.ranks[i][n-sl-1] break } sl += li } return ret }
func (u *Ugly) calNext() { var n = len(u.cbase) + 1 var bb = make([]int, len(u.base)) for i, b := range u.base { bb[i] = maxc(pow(u.bmul, n), b) } u.cbase = append(u.cbase, bb) bn := make([]int, len(bb)) var rank []int min := pow(u.bmul, n-1) for autoAdd(bn, bb) { pm := powmul(u.base, bn) if pm > min && pm <= pow(u.bmul, n) { rank = append(rank, pm) } } sort.Ints(rank) u.ranks = append(u.ranks, rank) }
func autoAdd(bn, ln []int) bool { if bn[0] < ln[0] { bn[0]++ return true } bn[0] = 0 if len(bn) == 1 { return false } return autoAdd(bn[1:], ln[1:]) }
func maxc(a, b int) int { return int(math.Log(float64(a)) / math.Log(float64(b))) }
func mul(nums []int) int { ret := 1 for _, n := range nums { ret *= n } return ret }
func sumLen(a [][]int) int { l := 0 for _, aa := range a { l += len(aa) } return l }
func pow(x, n int) int { if n == 0 { return 1 } ret := 1 for i := 0; i < n; i++ { ret *= x } return ret }
func powmul(a, b []int) int { var c = make([]int, len(a)) for i := range a { c[i] = pow(a[i], b[i]) } return mul(c) }
|