这题目用中途相遇法解太经典了,
先暴力存下前一半的所有解。然后暴力匹配下一半的解。用map做中间者,
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <cctype>
using namespace std;
typedef long long LL;
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep1(i,n) for(int (i)=1;(i)<=(n);(i)++)
#define int long long
const int maxn = 26;
map<int,int> d[maxn];
int fac[19],n,k,s,a[maxn];
int res = 0;
void dfs1(int p,int ed,int t,int sum){
if(p >= ed+1){
if(!d[t].count(sum)) d[t][sum]=1;
else d[t][sum]++;
return ;
}
dfs1(p+1,ed,t,sum);
if(a[p]<19&&t<k&&sum+fac[a[p]]<=s)
dfs1(p+1,ed,t+1,sum+fac[a[p]]);
if(sum+a[p]<=s) dfs1(p+1,ed,t,sum+a[p]);
}
void dfs2(int p,int ed,int t,int sum){
if(p == ed+1){
for(int i=0;i<=k-t;i++) {
if(d[i].count(s-sum)) res+=d[i][s-sum];
}
return ;
}
dfs2(p+1,ed,t,sum);
if(a[p]<19&&t<k&&sum+fac[a[p]]<=s)
dfs2(p+1,ed,t+1,sum+fac[a[p]]);
if(sum+a[p]<=s) dfs2(p+1,ed,t,sum+a[p]);
}
main()
{
fac[1] = 1;
for(int i=2;i<=18;i++) fac[i]=fac[i-1]*i;
scanf("%I64d %I64d %I64d",&n,&k,&s);
rep1(i,n) scanf("%I64d",&a[i]);
int mid =(n+1)/2;
dfs1(1,mid,0,0);
res = 0;
dfs2(mid+1,n,0,0);
cout<<res<<endl;
}