描述
小 Hi 手上有 n 张面值互不相同的钱币,且面值都是 2 的幂次,现在他想知道,他可以组合出多少种小于等于 c 的正整数金额。
输入
第一行两个正整数 n , c (1 ≤ n ≤ 50, 1 ≤ c ≤ 1018)
第二行n个互不相同的正整数,表示小Hi手上钱币的面值,保证面值都是 2 的幂次,且不超过 1018
输出
输出一个整数表示答案
样例提示
可以拼出 1, 4, 5, 8, 9
样例输入
3 10
4 1 8
样例输出
5
思路:
第一想法是枚举,但发现枚举的次数过多 关键是利用面值都是 2 的幂次从而减少递归的次数。我们可以发现 (1,4,8)1+4+8<28;
这意味着只要把输入的数排下序。只要找到 2ai<=c 就可以直接 pow(2,i)算出种数。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=60;
long long a[maxn];
long long dfs(long long x,long long g){
if(x==1)
return 1+(a[x]<=g);
if(2*a[x]<=g)
return (long long)pow(2,x);
long long root=dfs(x-1,g);
if(a[x]<=g) root+=dfs(x-1,g-a[x]);
return root;
}
int main(){
long long n,c;
cin>>n>>c;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
long long ans=dfs(n,c);
cout<<ans-1<<endl;
}