Fork me on GitHub

编程练习赛62

描述

小 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;
这意味着只要把输入的数排下序。只要找到 2
ai<=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;
}