c(n,0)加到c(n,n)的和为2的n次方。
刚开始暴力dfs所有的组合,结果超时,后来用折半查找过的,忘了判断取jie数组里面的数不能大于19,re了两次
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
void dis(int a[], int n){
printf("总数为%d个\n",n);
for(int i = 0; i < n; i++) cout<<a[i]<<", ";
cout<<endl<<"------------------"<<endl;
}
const int mx = 0;
int n,k,le,mi,ri;
int visa[26],visb[26];
ll s,ans,a[26],b[26],num[26],jie[21];
vector<ll>va[26];
vector<ll>vb[26];
void da (){
jie[1] = jie[0] = 1;
for(int i = 2 ; i < 19;i++){
jie[i] = jie[i-1] * i;
}
return;
}
void init(){
ans = 0;
memset(visa,0,sizeof(visa));
memset(visb,0,sizeof(visb));
for(int i = 0; i < 26; i++){
va[i].clear();
vb[i].clear();
}
}
void dfs1(int ge, ll sum, int cor){
/*if(sum > s)
return;*/
for(int i = cor; i < le; i++){
if(!visa[i]){
visa[i] = 1;
if(sum+a[i] <= s){
va[ge].push_back(sum+a[i]);
dfs1(ge,sum+a[i],i);
}
if(ge < k && a[i] < 19 &&(sum+jie[a[i]]) <= s){
va[ge+1].push_back(sum+jie[a[i]]);
dfs1(ge+1,sum+jie[a[i]],i);
}
visa[i] = 0;
}
}
}
void dfs2(int ge, ll sum, int cor){
/*if(sum > s)
return;*/
for(int i = cor; i < ri; i++){
if(!visb[i]){
visb[i] = 1;
if(sum+b[i] <= s){
vb[ge].push_back(sum+b[i]);
dfs2(ge,sum+b[i],i);
}
if(ge < k && b[i] < 19 &&(sum+jie[b[i]]) <= s){
vb[ge+1].push_back(sum+jie[b[i]]);
dfs2(ge+1,sum+jie[b[i]],i);
}
visb[i] = 0;
}
}
}
int main(){
da(); //打表求阶乘
while(scanf("%d%d%lld",&n,&k,&s) != EOF){
mi = n / 2;
for(int i = 0; i < n ;i++){
scanf("%lld",num+i);
}
le = ri = 0;
for(int i = 0; i < mi; i++){
a[le++] = num[i];
}
for(int i = mi; i < n; i++){
b[ri++] = num[i];
}
init(); // ans已被初始化
dfs1(0,0,0);
dfs2(0,0,0);
for(int i = 0; i <= k; i++)
sort(vb[i].begin(),vb[i].end());
ll te;
for(int i = 0; i <= k; i++)
for(int j = 0; (i+j) <= k; j++){
for(int k = 0; k<va[i].size();k++){
te = s - va[i][k];
ans+=(upper_bound(vb[j].begin(),vb[j].end(),te) - lower_bound(vb[j].begin(),vb[j].end(),te));
}
}
for(int i = 0; i <= k; i++)
for(int k = 0; k<vb[i].size();k++)
if(vb[i][k] == s)
ans++;
for(int i = 0; i <= k; i++)
for(int k = 0; k<va[i].size();k++)
if(va[i][k] == s)
ans++;
cout<<ans<<endl;
}
return 0;
}