小Q非常富有,拥有非常多的硬币,小Q的拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好> 各有两个数值为2^k,的硬币,所以小Q拥有的硬币是1,1,2,2,4,4……,小Q卖东西需要支付元钱,请问小Q想知道有多少种组合方案。 输入:一个n (1<=n<=10^18),代表要付的钱 输出:表示小Q可以拼凑的方案数目
参考答案
#coding=utf-8
import math
n = int(input())
def getMaxCoin(n):
tmp = int(math.log(n,2))
return 2**tmp
buff = {}
def dp(n, coin):
if (n, coin) in buff:
return buff[(n,coin)]
if n == 0: # 找0块钱,必然可以
return 1
if coin == 1: # 只用1元找
if n == 1 or n == 2:
return 1
return 0 # 当前面值无解
if n > coin * 4 -2:
return 0
ret = 0
# 只用了一枚
if n >= coin:
ret += dp(n-coin, coin//2)
if n >= coin*2:
# 用了两枚
ret += dp(n-coin*2, coin//2)
# 没有用
ret += dp(n, coin//2)
buff[(n,coin)] = ret
return ret
print(dp(n,getMaxCoin(n)))
思路: 对于当前的面额,最大可能用到的硬币面额可以通过getMaxCoin函数计算得到。 对于问题面额n和可以使用的最大硬币面额,求dp(n, coin)的值。 coin会不断减小,对于coin为1时,面额为1或2只有1种情况。对于面额为0时,不需要硬币就可以有解。对于面额大于coin*4-2时,超过了能找的上限,无解。对于其他情况,分三种情况,coin用了一枚,coin用了两枚,coin用了零枚。分别计算对应的dp值即可。使用buff缓存已经计算出来的面值。