首页 > 技术文章 > 洛谷P2396 yyy loves Maths VII【状压dp】

wyboooo 2019-07-09 20:04 原文

题目https://www.luogu.org/problemnew/show/P2396

题意:有n个数,每次选择一个表示走$a[i]$步,每个数只能选一次。

最多有两个厄运数字,如果走到了厄运数字就不能继续走下去了。

选完所有数有多少种方案。

思路:n很小,状压。

用state表示已经选了哪几个数。如果state是厄运数字就continue

不是的话state就需要加上所有是1的,这道题卡常,所以可以用上lowbit。再开O2优化。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<map>
 4 #include<set>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<cmath> 
 9 #include<stack>
10 #include<queue>
11 #include<iostream>
12 
13 #define inf 0x3f3f3f3f
14 #define lowbit(i) i&(-i)
15 using namespace std;
16 typedef long long LL;
17 typedef pair<int, int> pr;
18 
19 int n, m;
20 const int maxn = 25;
21 const int mod = 1e9 + 7;
22 int bad[3];
23 int dp[1 << maxn], dis[1 << maxn];
24 
25 
26 int main()
27 {
28     scanf("%d", &n);
29     for(int i = 0; i < n; i++){
30         scanf("%d", &dis[1 << i]);
31     }
32     scanf("%d", &m);
33     for(int i = 0; i < m; i++){
34         scanf("%d", &bad[i]);
35     }
36     dp[0] = 1;
37     int mx = 1 << n;
38     for(int i = 1; i < mx; i++){
39         dis[i] = dis[i ^ lowbit(i)] + dis[lowbit(i)];
40         if(dis[i] == bad[0] || dis[i] == bad[1])continue;
41         for(int j = i, k = lowbit(j); j; j ^= k, k = lowbit(j)){
42             dp[i] += dp[i ^ k];
43             if(dp[i] >= mod)dp[i] -= mod;
44         }
45     }
46     
47     printf("%d\n", dp[mx - 1]);
48     return 0;
49 }

 

推荐阅读