我的思路是用a记录菜的价格,b相当于一个桶记录价格为i的菜有几种
dfs每一种价格,往下搜索当前价格取i个的方案数,再乘上当前价格的菜品数量中取出i个菜的方案数,并往前递归
#include <iostream>
using namespace std;
inline int read(){//快速读入
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m, a[200],b[1005],cnt = 0;//a表示存在的菜品价格,b表示该价格有多少种菜品,b相当于一个桶
inline long long C(int n, int m){//组合数C
if(m == 0) return 0;
if(n == m) return 1;
long long ans = 1;
if(n - m > m){
for(int i = n-m+1; i <= n; i++){
ans *= i;
}
for(int i = 2; i <= m; i++){
ans /= i;
}
}else{
for(int i = m+1; i <= n; i++){
ans *= i;
}
for(int i = 2; i <= n-m; i++){
ans /= i;
}
}
return ans;
}
inline int dfs(int step, int ans){//step表示当前进行到第几种价格的菜品,ans表示已经选了多少圆的菜
int sum = 0;//从当前函数开始算一共有多少种取法
if(step == cnt+1){
if(ans == m) return 1;
return 0;
}
if(ans > m){
return 0;
}
for(int i = 0; i <= b[a[step]]; i++){
if(dfs(step+1,ans + a[step] * i)){//当前价格的菜品取i种
sum += C(b[a[step]],i) * dfs(step+1,ans + a[step] * i);//乘法原理
}
}
return sum;
}
int main(){
n = read(),m = read();
while(n--){//读入并去重
cin >> a[++cnt];
b[a[cnt]]++;
if(b[a[cnt]]!=1){
cnt--;
}
}
cout << dfs(1,0)<< endl;
return 0;
}