Anya and Cubes

题目:

给你n个数,n≤26 初始序列为ai​,1≤ai≤1e9
你有k个! ,每个!可以使序列中的一个数变成ai!(k不一定要用完)
例如5!=120
求:选出任意个数使他们和的等于S的方案数(0≤S≤1e16)
思路:

三种情况深度遍历,贴变阶乘,不贴取原值,不贴不取,把n分一半左右分别遍历;

dfs1当used贴纸数大于k返回;当左区间越过右区间返回;

dfs2当used贴纸数大于k返回;当当前总和大于所有总和返回;当左区间越过右区间,取所有可能使总和-已有和的可能,返回。

20的阶乘大于1e16,所以在阶乘判断时a[i]小于20。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<stack>
 7 #include <bitset>
 8 #include<set>
 9 #include<map>
10 #include<unordered_map>
11 #include<vector>
12 #include<cmath>
13 #include<string>
14 using namespace std;
15 const int N = 30;
16 unordered_map<long long, long long>M[N];
17 long long fact[N];
18 int n, k, a[N];
19 long long s, ans;
20 void dfs1(int now, int end, long long S, int used) {
21   //  cout << "dfs1(" << now << "," << end << "," << S << "," << used << ")" << endl;
22     if (used > k)
23         return;
24     if (now > end) {
25         M[used][S] ++;
26   //      cout << "M[" << used << "][" << S << "]" << "=" << M[used][S] << endl;
27         return;
28     }
29     dfs1(now + 1, end, S, used);
30     dfs1(now + 1, end, S + a[now], used);
31     if (a[now] <= 20)
32         dfs1(now + 1, end, S + fact[a[now]], used + 1);
33 }
34 
35 void dfs2(int now, int end, long long S, int used) {
36   //  cout << "dfs1(" << now << "," << end << "," << S << "," << used << ")" << endl;
37     if (used > k)
38         return;
39     if (S > s)
40         return;
41     if (now > end) {
42         for (int i = 0; i <= k - used; i++) {
43             ans += M[i][s - S];
44  //           cout << "ans+=" << M[i][s - S] << " " << "ans=" << ans << endl;
45         }
46         return;
47     }
48     dfs2(now + 1, end, S, used);
49     dfs2(now + 1, end, S + a[now], used);
50     if (a[now] <= 20)
51         dfs2(now + 1, end, S + fact[a[now]], used + 1);
52 }
53 int main() {
54     cin >> n >> k >> s;
55     fact[1] = 1;
56     for (int i = 2; i <= 20; i++)
57         fact[i] = fact[i - 1] * i;
58     for (int i = 1; i <= n; i++)
59         cin >> a[i];
60     dfs1(1, (n + 1) / 2, 0, 0);
61     cout << endl << endl;
62     dfs2((n + 1) / 2 + 1, n, 0, 0);
63     cout << ans << endl;
64     return 0;
65 }

链接:https://www.luogu.com.cn/problem/solution/CF525E

posted @ 2020-07-20 10:49  吉吉的奥利奥  阅读(144)  评论(0编辑  收藏  举报