CodeForces Round #297 Div.2 E (中途相遇法)

当时打比赛的时候卡在D题了,没有看E。现在看来E还是不难的。

将n个数排序后,其实不排序也是可以的,只是排序能快一半的时间。

枚举前一半能得到多少种和,放到map里面;

然后在后一半数中枚举,然后在map里面查找。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 const int maxn = 30;
 6 LL a[maxn], f[maxn], S, ans;
 7 int n, m, k;
 8 
 9 map<int, LL> cnt[maxn];
10 
11 void dfs(int d, int used, LL s, int type)
12 {
13     if(d == m)
14     {
15         if(type == 0) cnt[used][s]++;
16         else for(int i = 0; i + used <= k; i++) if(cnt[i].count(S - s)) ans += cnt[i][S - s];
17         return;
18     }
19     dfs(d + 1, used, s, type);
20     if(s + a[d] <= S) dfs(d + 1, used, s + a[d], type);
21     if(a[d] < 19 && used < k && s + f[a[d]] <= S) dfs(d + 1, used + 1, s + f[a[d]], type);
22 }
23 
24 int main()
25 {
26     f[0] = f[1] = 1;
27     for(int i = 2; i < 19; i++) f[i] = f[i - 1] * i;
28     cin >> n >> k >> S;
29     for(int i = 0; i < n; i++) cin >> a[i];
30     sort(a, a + n);
31     m = n / 2;
32     dfs(0, 0, 0, 0);
33     m = n;
34     dfs(n / 2, 0, 0, 1);
35     cout << ans << endl;
36 
37     return 0;
38 }
代码君

 

posted @ 2015-05-06 20:43  AOQNRMGYXLMV  阅读(149)  评论(0编辑  收藏  举报