HDU 5117 2014ICPC北京現場賽 F - Fluorescent (狀壓DP)
阿新 • • 發佈:2018-11-10
有n個燈和m個開關,每個開關控制一些燈,顯然開關的狀態有2^m種。設亮著的燈的數目為x,求所有狀態下x^3之和。
n,m <= 50顯然不能直接計算每種x進行dp的。考慮直接計算x^3。
x^3 = (x1 + x2 + ... + xn)* (x1 + x2 + ... + xn)* (x1 + x2 + ... + xn) = Sum(xi * xj * xk)。
列舉i,j,k3個開關,然後用dp[m][S]表示用前m個開關達到狀態S的方案數,每次加上dp[m][7]即可。因為對x^3產生貢獻的條件就是xi,xj,xk同時為1也就是狀態7。
總的時間複雜度O(n^3*m)。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> #include <vector> using namespace std; typedef long long ll; const int maxn = 55; const ll mod = 1e9 + 7; int t, n, m, p, x; ll dp[maxn][8], num[maxn]; int main() { scanf("%d", &t); int kase = 0; while(t--) { scanf("%d%d", &n, &m); memset(num, 0, sizeof(num)); for(int i = 1;i <= m;i++) { scanf("%d", &p); while(p--) { scanf("%d", &x); num[i] |= (1LL << x); } } ll ans = 0; for(int i = 1; i<= n;i++) { for(int j = 1;j <= n;j++) { for(int k = 1;k <= n;k++) { memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for(int o = 1;o <= m;o++) { for(int u = 0;u <= 7;u++) { int tmp = u; if(num[o] & (1LL<<i)) tmp ^= 1; if(num[o] & (1LL<<j)) tmp ^= 2; if(num[o] & (1LL<<k)) tmp ^= 4; dp[o][u] += dp[o-1][u]; dp[o][tmp] += dp[o-1][u]; } } ans = (ans + dp[m][7]) % mod; } } } printf("Case #%d: %lld\n", ++kase, ans); } return 0; }