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; }