题意:n个开关,每个控制一些灯,最后求E[X3] × 2M mod (109 + 7)
思路 : 另xi代表每个灯的状态,原始等价(x1+x2+..xn)(x1+..xn)(x1+..xn),乘2的M次方等价于对开关的每一种选择结果直接加上和,即对每一种开关状态所有xi*xj*xk不为一累加上即可,因此对 xi*xj*xk可反求有多少种控制方式使得结果为一,dp。最后可枚举每项前系数来节省时间,当i和j和k不相等系数为6,同理。
#include <iostream>
#include <cstdio>#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 55;
int t,n,m,a[maxn][maxn];
ll dp[maxn][8];
void solve(int x,int y,int z) {
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i <= m; i++) {
int temp = 0;
for (int j = 1; j <= a[i][0]; j++) {
if (a[i][j] == x) temp += 4;
if (a[i][j] == y) temp += 2;
if (a[i][j] == z) temp += 1;
}
for (int j = 0; j <= 7; j++) {
dp[i][j^temp] = (dp[i][j^temp]+dp[i-1][j])%mod;
dp[i][j] = (dp[i][j]+dp[i-1][j])%mod;
}
}
return ;
}
int main() {
int kase = 0;
scanf ("%d",&t);
while(t--) {
scanf ("%d%d",&n,&m);
for (int i = 1; i <= m; i++) {
scanf ("%d",&a[i][0]);
for (int j = 1; j <= a[i][0]; j++) scanf ("%d",&a[i][j]);
}
ll ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
for (int k = j; k <= n; k++) {
int first = 0;
if (i == j && j == k) first = 1;
else if (i == j || j == k || i == k) first = 3;
else first = 6;
solve(i,j,k);
ans = (ans+(first*dp[m][7])%mod)%mod;
}
}
}
printf ("Case #%d: %lld\n",++kase,ans);
}
return 0;
}