[Codeforces Round #297 Div. 2] E. Anya and Cubes

http://codeforces.com/contest/525/problem/E

学习了传说中的折半DFS/双向DFS

先搜前一半数,记录结果,然后再搜后一半数,匹配之前结果。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<map>
 7 #define LL long long
 8 using namespace std;
 9 const int mxn=1200000;
10 struct data{
11     LL x,sum;
12 }b[mxn];//
13 int tot=0;
14 map<LL,LL>mp[30];//用[i]次阶乘,和为[j]的方案数 
15 LL n,k,s;
16 LL a[mxn];
17 LL p[30];
18 void DFS(LL cnt,LL t,LL now,int ed){
19     if(now>s || t>k)return;
20     if(cnt>ed){
21         if(ed==n/2){
22             tot++;
23             b[tot].x=t;
24             b[tot].sum=now;
25         }
26         else{
27             mp[t][now]++;
28         }
29         return;
30     }
31     DFS(cnt+1,t,now,ed);//不选 
32     DFS(cnt+1,t,now+a[cnt],ed);//
33     if(a[cnt]<19)DFS(cnt+1,t+1,now+p[a[cnt]],ed);//选阶乘*/
34     return; 
35 }
36 void init(){
37     p[1]=1;
38     for(int i=2;i<19;i++){
39         p[i]=p[i-1]*i;
40     }
41 }
42 int main(){
43     init();
44     scanf("%I64d%I64d%I64d",&n,&k,&s);
45     int i,j;
46     for(i=1;i<=n;i++)scanf("%d",&a[i]);
47     int mid=n/2;
48     DFS(1,0,0,mid);
49     DFS(mid+1,0,0,n);
50     LL ans=0;
51     for(i=1;i<=tot;i++){
52         for(j=0;j<=k-b[i].x;j++){//可以不使用阶乘,所以从0开始 
53             ans+=mp[j][s-b[i].sum];
54         }
55     }
56     printf("%I64d
",ans);
57     return 0;
58 }
原文地址:https://www.cnblogs.com/SilverNebula/p/5836976.html