蓝桥20182 知识考量码:递归
https://www.lanqiao.cn/problems/20182/learning/?page=1&first_category_id=1
我们把n,k的解记为solve(n,k),记k的二进制位数为v
把这个问题划分成2个部分,一个是序列中存在第v-1位为1的情况,一个是序列中不存在第v-1位为1的情况。
如果序列中所有元素第v-1位都为0,那么剩下的v-2 ~ 0位都可以无约束地取0或者1
由于题目要求的性质,如果在序列中index = i位置,元素的第x位首次为1,那么在此之后的元素这位就始终为1.
这样,只要考虑v-2~0位的1首次出现的index,即可求出这部分的序列数量:
每个位的1,可能首次出现在index = 0 ~ n - 1, 也可能直接不出现,共 n + 1 种可能。
这部分的序列数量就是:(n + 1) ^ (v - 1)
然后考虑序列中存在第v-1位为1的情况:
这部分可以递归计算,对应的子问题是solve(n, k - (1 << (v-1))),然后第v-1位的1可能出现index = 0 ~ n - 1, 所以要乘n
举个例子:求n = 3, k = 10, 序列中存在大于等于8的元素的序列个数,记这个问题为sub_solve(3,10):
表达式为 sub_solve(3,10) = 3 * solve(3, 2)
solve(3,2) = 4 ^ 1 + 3 * solve(3, 0) = 7
具体的,solve(3,2)中的所有序列为:(0,0,0), (0,0,1), (0,0,2), (0,1,1), (0,2,2), (1,1,1), (2,2,2),其中每个序列可以转化得到3个sub_solve(3,10)中的序列
例如(0,0,0) -> (0,0,8), (0,8,8), (8,8,8)
n, k = map(int, input().split())
MOD = 10 ** 9 + 7
def solve(n, k):
if k == 0:
return 1
v = len(bin(k)) - 3
return (pow(n + 1, v) + n * solve(n, k - (1 << v))) % MOD
print(solve(n, k))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架