HDU 5117 Fluorescent

题目链接:HDU-5117

题意为有n盏灯,m个开关,每个开关控制着( k_{i} )灯。X为最后亮着的灯的个数,要求出( E(X^{3} ) * 2^{M} mod (10^9 + 7) )。

可以看出(  E(X^{3} ) * 2^{M} = sum (X^{3} * (frac{1}{2})^{m}) * 2^{m} = sum X^{3} )

然后将 (   sum X^{3}  ) 分解为( sum X^{3} = sum_{i,j,k = 1}^{n} x_{i} * x_{j} * x_{k}  )

于是问题就转化成了求对于所有的i,j,k,有多少种情况i,j,k都亮着。

于是我们可以写出状态转移方程f[i][j][k][state][ii] = f[i][j][k][state][ii-1] + f[i][j][k][state ^ ( switch_{ii})][ii-1];

其中f[i][j][k][state][ii]表示使用前ii个开关使i,j,k的状态为state的方案数。

我们发现i,j,k其实没有必要记录。所以进一步,我们可以把方程优化为f[state][ii] = f[state][ii-1] + f[state ^ switch[ii]][ii-1];

另外还有一个需要注意的小细节是注意使用1LL。

代码如下:

 1 #include<cstdio>
 2 #include<set>
 3 #include<map>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<iostream>
 8 using namespace std;
 9 typedef long long LL;
10 
11 const LL MOD = 1e9 + 7;
12 const LL MAXN = 60;
13 LL d[MAXN];
14 int main()
15 {
16 #ifdef LOCAL
17     freopen("in.txt","r",stdin);
18 #endif
19     LL t;
20     scanf("%lld",&t);
21     for(LL tt = 1; tt <= t; tt++)
22     {
23         memset(d,0,sizeof(d));
24         LL n,m;
25         scanf("%lld%lld", &n, &m);
26         for(LL i = 1; i <= m; i++)
27         {
28             LL k;
29             scanf("%lld", &k);
30             for(LL j = 1; j <= k; j++)
31             {
32                 LL tmp;
33                 scanf("%lld", &tmp);
34                 d[i] += (1LL << (tmp-1));
35             }
36         }
37         LL ans=0;
38         for(LL i = 1; i <= n; i++)
39             for(LL j = 1; j <= n; j++)
40                 for(LL k = 1; k <= n; k++)
41                 {
42                     LL f[8][MAXN];
43                     memset(f,0,sizeof(f));
44                     f[0][0]=1;
45                     for(LL ii = 1; ii <= m; ii++)
46                     {
47                         LL ss=0;
48                         if(d[ii] & (1LL << (i-1))) ss ^= 1;
49                         if(d[ii] & (1LL << (j-1))) ss ^= 2;
50                         if(d[ii] & (1LL << (k-1))) ss ^= 4;
51                         for(LL jj=0;jj<=7;jj++)
52                         {
53                             f[jj][ii] += f[jj][ii-1];
54                             f[jj][ii] += f[jj ^ ss][ii - 1];
55                         }
56                     }
57                     ans = (ans + f[7][m]) % MOD;
58                     //printf("%lld %lld %lld %lld
", i, j, k, ans);
59                 }
60         printf("Case #%lld: %lld
", tt, ans);
61     }
62     return 0;
63 }
原文地址:https://www.cnblogs.com/zarth/p/6510328.html