首页 > 试题广场 >

拼凑硬币

[编程题]拼凑硬币
  • 热度指数:6718 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解

小Q十分富有,拥有非常多的硬币,小Q拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好各有两个面值为2^K的硬币,所以小Q拥有的硬币就是1,1,2,2,4,4,8,8,…。小Q有一天去商店购买东西需要支付n元钱,小Q想知道有多少种方案从他拥有的硬币中选取一些拼凑起来恰好是n元(如果两种方案某个面值的硬币选取的个数不一样就考虑为不一样的方案)。

 


输入描述:
输入包括一个整数n(1≤n≤10^18),表示小Q需要支付多少钱。注意n的范围。


输出描述:
输出一个整数,表示小Q可以拼凑出n元钱放的方案数。
示例1

输入

6

输出

3
Num = int(input())
dp = {0: 0, 1: 1, 2: 2}
def dfs(n):
    if n < 3:
        return dp[n]
    else:
        if n in dp:
            return dp[n]
        if n % 2 == 0:               # n为偶数时,要么选取0个1,要么选取2个1.
            dp[n] = dfs(n >> 1) + dfs((n-2) >> 1)
            return dp[n]
        else:                        # n为奇数时,单个1为必选项,转而考虑偶数n-1,
            dp[n] = dfs((n-1) >> 1)  # 此时偶数n-1完全由多个2的k(k>0)次幂相加而成
            return dp[n]             # 等式两边同除2,解集个数不变,可得转态转移方程
print(dfs(Num))
编辑于 2020-08-22 15:08:33 回复(0)
import math
import sys
n = int(sys.stdin.readline().strip())
plans = {0:1, 1:1}

def findPlans(n):
    if n < 0:
        return 0
    if n in plans:
        return plans[n]
    else:
        maxk = int(math.log2(n))
        # the 1th keypoint is find (5) in total sum is equal to find (sum-5) in total sum
        # also, sum is 2**(m+1)-2 = \sum_{k=0}^{m}{2**k*2} is the 2nd keypoint
        # So, this line means, use or not use the max-available-value coin
        nums = findPlans(n-2**maxk) + findPlans(2**(maxk)*2 - 2 - n)
        plans[n] = nums
        return nums
print(findPlans(n))

# sorry for English only since this pc doesn't have sougou
发表于 2019-03-12 07:58:49 回复(0)
import sys
import math
n = int(sys.stdin.readline())
mem = {-1:0,0:1,1:1}

def get_num(n):
    if n in mem:
        return mem[n]
    else:
        m = int(math.log2(n))
        ans = get_num(n-2**m) + get_num(2**(m+1)-2-n)
        mem[n] = ans
        return ans
print(get_num(n))

对题目进行分析不难发现应该是使用递推法,然后要点有两个
1.递推时需要取反,具体来说,对于 n = 5,我们用1个4,那么就有a1种可能,如果我们不用4,那么正着分析很难。但是1,1,2,2最多能凑6,那么我们考虑从这里面删去1凑5,那么方法树还是a1.
2.具体实现时由于n 过于大,所以不能直接申请数组,会直接超时,这里我们使用动态规划的记忆化搜索策略,使用辅助字典来缓存结果。
初步估计复杂度应该是O(logN).
编辑于 2019-01-14 22:02:30 回复(5)