链接:点击打开链接
题意:给出n个数,任意选择一些数,并在被选择的这些数中选择最多k个变成阶乘,求这些数和为s的种数
代码:
#include <map>
#include <set>
#include <queue>
#include <string>
#include <math.h>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
int k,a[30];
long long S,ans,f[30];
map<long long,int> mp[30];
void dfs1(int st,int en,int op,long long sum){
if(sum>S||op>k)
return;
if(st==en){
mp[op][sum]++;
return;
}
dfs1(st+1,en,op,sum);
dfs1(st+1,en,op,sum+a[st]);
if(a[st]<20)
dfs1(st+1,en,op+1,sum+f[a[st]]);
}
void dfs2(int st,int en,int op,long long sum){
int i;
if(sum>S||op>k)
return;
if(st==en){
for(i=0;i<=k-op;i++) //先用count判断一下是否存在就不t
if(mp[i].count(S-sum))
ans+=mp[i][S-sum];
return;
}
dfs2(st+1,en,op,sum);
dfs2(st+1,en,op,sum+a[st]);
if(a[st]<20)
dfs2(st+1,en,op+1,sum+f[a[st]]);
}
int main(){
int i,n;
f[0]=1;
for(i=1;i<=20;i++)
f[i]=f[i-1]*i;
while(scanf("%d%d%I64d",&n,&k,&S)!=EOF){
for(i=0;i<n;i++){ //折半搜,第二次搜的时候和第一次合并
scanf("%d",&a[i]);
mp[i].clear();
}
ans=0;
dfs1(0,n/2,0,0);
dfs2(n/2,n,0,0);
printf("%I64d\n",ans);
}
return 0;
}