Project Euler 113

Project Euler 113

题目

Non-bouncy numbers

Working from left-to-right if no digit is exceeded by the digit to its left it is called an increasing number; for example, $134468$.

Similarly if no digit is exceeded by the digit to its right it is called a decreasing number; for example, $66420$.

We shall call a positive integer that is neither increasing nor decreasing a “bouncy” number; for example, $155349$.

As $n$ increases, the proportion of bouncy numbers below n increases such that there are only $12951$ numbers below one-million that are not bouncy and only $277032$ non-bouncy numbers below $10^{10}$.

How many numbers below a googol ($10^{100}$) are not bouncy?

解决方案

所谓的上升数和下降数,下一位的值只能都大于等于上一位或者小于等于上一位。因此可以用动态规划的方法统计$n$位数的上升数和下降数。

分别设两个状态$f(i,d),g(i,d)(1\le i\le n,0\le d\le 9)$表示$i$位数中,个位为$d$的上升数/下降数分别有多少个。

注意到上升数的每一位中,下一位的值只能都大于等于上一位,可以列出$f(i,j)$的状态转移方程:

类似的,可以列出$g(i,j)$的状态转移方程:

注意到,$111\dots111,222\dots222$这种$n$位都是一样的数都算进了上升数和下降数中,因此最终答案需要减去这两种数多算的一次。

最终答案为:

代码

1
2
3
4
5
6
7
8
9
10
11
N = 100
f = [1 for _ in range(10)]
f[0] = 0
g = f.copy()
ans = 9
for i in range(N - 1):
f = [sum(f[:i + 1]) for i in range(10)]
g = [sum(g[i:]) for i in range(10)]
ans += sum(f) + sum(g) - 9
print(ans)