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 }