HDU——2566 统计硬币 (简单枚举 || 母函数)

Problem Description

假设一堆由1分、2分、5分组成的n个硬币总面值为m分,求一共有多少种可能的组合方式(某种面值的硬币可以数量可以为0)。

Input

输入数据第一行有一个正整数T,表示有T组测试数据;
接下来的T行,每行有两个数n,m,n和m的含义同上。

Output

对于每组测试数据,请输出可能的组合方式数;
每组输出占一行。

Sample Input

2
3 5
4 8

Sample Output

1
2

解题思路:

方法一 : 拿到这个题目 , 三层循环就可以解决,但是时间复杂度太高 ,为O(n^3).此基础上,因为总量是确定的,确定了前两个的个数之后 , 第三个也能够确定 , 所以可以减少一层循环,时间复杂度也可以相对降低一点 , 为 O(n^2).
代码:

//方法一 直接枚举 , 时间复杂度为 O(n^2)
/*
#include 
#include 
using namespace std;

int value[4] = {0 , 1 , 2 , 3};
int main(){
    int t , n , m , i , j , k ,ans;
    scanf("%d", &t);
    while( t --){
        ans = 0;
        scanf("%d %d",&n , &m);
        for(i = 0 ; i <= n ; i ++){
            for(j = 0 ; j + i <= n ; j ++){
                    if(1 * i + 2 * j + 5 * (n - i - j) == m)
                        ans ++;
            }
        }
        printf("%d\n" , ans);
    }
    return 0;
}

方法二:因为当只要考虑面值为 1 和 2 的硬币的组合情况时 , 当总面值确定时 , 每一个总面值有也仅有一种组合情况 。 利用一点 , 我们可以先确定面值为 5 的纸币的数量,然后在考虑面值1和2 , 这样时间复杂度就可以很大的降低 ,为 O(m).
代码:

//方法二 加了那么一点点技巧 , 主要时间复杂度可以降低很多
//考虑如果只有面值为1、2的硬币n枚。那么能够唯一组成区间[n,2n]范围里的任意面值。

#include 
using namespace std;

int main(){
    int t , n , m , i,ans;
    scanf("%d", &t);
    while( t --){
        ans = 0;
        scanf("%d %d",&n , &m);
        for(i = 0 ; i <= m/5 && i <= n; i ++){  //首先确定面值为5 的硬币可能出现的张数。
            int temp = m - i*5;  //剩下的面值
            int tempcount = n - i;  //剩下的张数

            if(tempcount * 1 <= temp && tempcount * 2 >= temp)
                ans ++;
        }
        printf("%d\n" , ans);
    }
    return 0;
}

你可能感兴趣的:(#,母函数)