[洛谷P2396]yyy loves Maths VII $\&$ [CF327E]Axis Walking
这道题是一个状压动归题。子集生成,每一位表示是否选择了第$i$个数。
转移:$f[S] = \sum f[S-\{x\}]$且$x\in S$,当该子集所有元素的和为$b_1$或$b_2$时不转移。
初始化:$f[\{\}]=1$,其他为$0$。
目标:$f[全集]$。
注意常数即可。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define inf (1 << 30) 12 13 inline int read() { 14 int w = 0, f = 1; char c = getchar(); 15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 17 return w * f; 18 } 19 20 int f[1 << 24], dis[1 << 24], n, m, b[3]; 21 const int Mod = 1000000007; 22 23 #define mod(x) (x>=Mod?x-Mod:x) 24 25 int main() { 26 n = read(); 27 rep(i, 1, n) dis[1<<(i-1)] = read(); 28 m = read(); 29 rep(i, 1, m) b[i] = read(); 30 f[0] = 1; 31 rep(i, 1, (1<<n)) { 32 dis[i] = dis[i&(i-1)] + dis[i&-i]; 33 if (dis[i] == b[1] || dis[i] == b[2]) continue; 34 for (register int x = i; x; x &= (x-1)) f[i] = mod(f[i]+f[i^x&-x]); 35 } 36 printf("%d", f[(1<<n)-1]); 37 return 0; 38 }