num = [int(ch) for ch in str(n)]
n = len(num)
@cache
def f(i,tight,c):
if i == n : return c
return sum(
f(i+1,tight and x==num[i],c + (x==1))
for x in range(10)
if not tight or x <= num[i]
)
return f(0,1,0)
def default_val(i,first = True):
return [0 ,first ]
def reduce_op(res1,res2):
return [res1[0]+res2[0],res1[1]+res2[1]]
def composition(u,v,res_v) :
return [res_v[0] + res_v[1],res_v[1]]
g = [[] for _ in range(n)]
for u, v in edges:
g[u].append(v)
g[v].append(u)
parent = [-1] * n
order,stack = [0], [0]
while stack:
u = stack.pop()
g[u] = [v for v in g[u] if v != parent[u]] #去掉父亲
for v in g[u]:
parent[v] = u
order.append(v)
stack.append(v)
down = [None] * n
parent_down_without_me = [None] * n
for me in reversed(order):
res = default_val(me,True)
for son in g[me]:
parent_down_without_me[son] = res
res = reduce_op(composition(me,son,down[son]),res)
down[me] = res
res = default_val(me,False)
for son in reversed(g[me]):
parent_down_without_me[son] = reduce_op(res,parent_down_without_me[son])
res = reduce_op(composition(me,son,down[son]),res)
up = [default_val(0,False) ] + [None] * (n-1)
for i in order[1:]:
up[i] = composition(i,parent[i],reduce_op(up[parent[i]],parent_down_without_me[i]))
updown = [reduce_op(x,y) for x,y in zip(up,down)]