首页 > 试题广场 >

换钱的方法数

[编程题]换钱的方法数
  • 热度指数:7363 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定数组arr,设数组长度为n,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱的方法数有多少种。由于方法的种数比较大,所以要求输出对进行取模后的答案。

输入描述:
输出包括两行,第一行包括两个整数n和aim。第二行包含n个整数,表示arr数组


输出描述:
输出一个整数,表示换钱的方法数对取模后的答案。
示例1

输入

4 15
5 10 25 1

输出

6

说明

5*3=15

10*1+5*1=15

10*1+1*5=15

1*10+5*1=15

5*2+1*5=15

1*15=15
示例2

输入

5 1000
2 3 5 7 10

输出

20932712

备注:
时间复杂度,空间复杂度
# -*- coding: utf-8 -*-
# !/usr/bin/python3

import sys

while True:
    s = sys.stdin.readline().strip()
    if s == '':
        break
    else:
        n, t = s.split()
        n = int(n)
        t = int(t)

        arr = list(map(int, input().split()))
        arr = sorted(arr)

        res = [0 for i in range(t + 1)]
        res[0] = 1

        for i in arr:
            if i > t:
                break
            for j in range(i, t + 1):
                res[j] = res[j] + res[j - i]

        # 输出一个整数,表示换钱的方法数对10 ^ 9 +7取模后的答案。
        print(res[t] % (pow(10, 9) + 7))
        
'''
解题思路:
动态规划核心状态转移方程式
f(n) = f(n - arr[0]) + f(n - arr[1]) + f(n - arr[2]) + ... + f(n - arr[i]) i为arr的长度
对于组成n的情况,每个arr[i]元与f(n - arr[i])都可以组成一个n,所以把每种f(n - arr[i])的种类数
相加,就找出了arr能组成n的种类。递归计算会重复计算f(n - arr[i]),运用斐波那契数列类似的方法,
从0开始遍历,重复利用计算过的f(n - arr[i])。结果数值会过大,题目要求输出对10 ^ 9 +7取模后的答案。
'''

发表于 2019-11-14 19:15:07 回复(0)
def count_way(arr, n):
    # 第0位是辅助位,代表面额数刚好等于金钱数的一种情况
    dp = [1] + [0]*n               # 不用任意面额的组合数
    for num in arr:
        for j in range(num, n+1):
            dp[j] += dp[j-num]
    return dp[-1]%(1000000007)
_,n = list(map(int, input().split(' ')))
arr = list(map(int, input().split(' ')))
print(count_way(arr, n))
同样是动态规划,python比其他语言慢了好多
编辑于 2019-08-10 14:11:29 回复(0)