HDU 5117(简单背包dp)

本题目的意思,就是有n个灯泡,和m个开关,每个开关控制着一些灯的明亮,求所有在2^m种选择下,所有明着的灯三次方总和,

定义xi 为第i盏灯的明亮情况0代表不明,1,代表名

X^3 = (x1 + x2 + x3 .. xn)*(x1 + x2 + x3 .. xn)*(x1 + x2 + x3 .. xn) 所以可以分开求在三盏灯为i,j,k 时所有情况个数,也就是这三盏灯对答案的贡献。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <cctype>
#include <cmath>
#include <queue>
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem(a,n) memset(a,n,sizeof(a))
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define rep1(i,x,y) for(int i=x;i<=(int)y;i++)
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000")
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll oo = 1e12;
typedef pair<ll,ll> pll;
const int mod = 1e9+7;

const int N = 55;
int a,b,c,n,m;
int st[N][N];
bool vis[N][8];
int d[N][8];
inline int tran(int p,int s){
  if(st[p][a]) s^=1;
  if(st[p][b]) s^=2;
  if(st[p][c]) s^=4;
  return s;
}
int main()
{
   int T,kase=1;
   scanf("%d",&T);
   while(T--){
      scanf("%d %d",&n,&m);
      memset(st,0,sizeof(st));
      rep1(i,1,m){
         int x,y; scanf("%d",&x);
         rep1(j,1,x) scanf("%d",&y),st[i][y]=1;
      }
      ll ans = 0;
      for(a=1;a<=n;a++)
         for(b=1;b<=n;b++)
              for(c=1;c<=n;c++){
                 for(int i=7;i>=0;i--) d[m+1][i]=(i==0);
                 for(int i=m;i>=1;i--)
                    for(int j=0;j<=7;j++)
                       d[i][j] = (d[i+1][j]+d[i+1][tran(i,j)])%mod;
                 ans = (ans + d[1][7])%mod;
              }
      printf("Case #%d: %d\n",kase++,(int)ans);
   }
   return 0;
}


你可能感兴趣的:(HDU 5117(简单背包dp))