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 <cstdio>
#include <cstring>
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 <cstdio>
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;
}