拼凑硬币
题目描述:
小Q十分富有,拥有非常多的硬币,小Q拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好各有两个面值为2^K的硬币,所以小Q拥有的硬币就是1,1,2,2,4,4,8,8,…。小Q有一天去商店购买东西需要支付n元钱,小Q想知道有多少种方案从他拥有的硬币中选取一些拼凑起来恰好是n元(如果两种方案某个面值的硬币选取的个数不一样就考虑为不一样的方案)。
参考了题解中的答案,感叹太强了;
(recur(n-2^m)) 代表了使用最大的 (2^m)来构建n,这里边需要转换一下思维,我没法直接找使用了(2^m)的方法数,
但是这个方法数实际上和构建((n-2^m))的个数是相同的;
(recur(2**(m+1)-2-n)) 代表了不使用(2^m)来构建n,这个需要这样理解,不使用(2^m),说明现在剩了2副(2^0,cdots,2^(m-1)),这里面加起来正好是(2^(m+1)-2),同样使用上述思想,便可以表示。只能说,真的太强了;
import sys
import math
n = int(sys.stdin.readline())
mem = {-1:0,0:1,1:1}
def recur(n):
if n in mem:
return mem[n]
else:
m = int(math.log2(n))
res = recur(n-2**m)+recur(2**(m+1)-2-n)
mem[n] = res
return res
print(recur(n))