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
|
func countNonDecreasing(l, r string, b int) int {
const mod = 1_000_000_007
var dp [101][11][2][2]int
var dfs func(pos, prev int, tightL, tightR bool, digitsL, digitsR []int) int
dfs = func(pos, prev int, tightL, tightR bool, digitsL, digitsR []int) int {
if pos == len(digitsR) {
return 1
}
if dp[pos][prev][boolToInt(tightL)][boolToInt(tightR)] != -1 {
return dp[pos][prev][boolToInt(tightL)][boolToInt(tightR)]
}
res := 0
low := 0
high := b - 1
if tightL {
low = digitsL[pos]
}
if tightR {
high = digitsR[pos]
}
for d := low; d <= high; d++ {
if d < prev {
continue
}
res = (res + dfs(pos+1, d, tightL && d == low, tightR && d == high, digitsL, digitsR)) % mod
}
dp[pos][prev][boolToInt(tightL)][boolToInt(tightR)] = res
return res
}
// Helper to convert string to digits in base b
toDigits := func(s string, base int, length int) []int {
res := make([]int, length)
num := new(big.Int)
num.SetString(s, 10)
for i := length - 1; i >= 0; i-- {
res[i] = int(new(big.Int).Mod(num, big.NewInt(int64(base))).Int64())
num.Div(num, big.NewInt(int64(base)))
}
return res
}
length := len(r)
digitsL := toDigits(l, b, length)
digitsR := toDigits(r, b, length)
for i := range dp {
for j := range dp[i] {
for k := range dp[i][j] {
for m := range dp[i][j][k] {
dp[i][j][k][m] = -1
}
}
}
}
boolToInt := func(b bool) int {
if b {
return 1
}
return 0
}
return dfs(0, 0, true, true, digitsL, digitsR)
}
|