題意:n盞燈,m個開關,每個開關控制一些燈,用1表示控制,0表示不控制,異或爲1時這盞燈亮,每個開關可開可不開,概率相同。現在問E(x^3)*(2^m),E爲期望,x爲亮燈數。
分析:如果求的是E[x]*(2^m),則可以考慮每一盞燈的狀態,O(m)求出使這盞燈亮的方案數。
現在求每種方案下,(x1+x2+x3+...+xn)^3,用0表示不亮,1表示亮,展開即爲C*xi*xj*xk,當i,j,k兩兩不同時C=6,一對相同時C=3,全部相同時C=1。
這樣就考慮每3盞燈的狀態,O(m)求出,累加即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<ostream>
#include<istream>
#include<algorithm>
#include<queue>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define fi first
#define se second
#define ll long long
#define pii pair<int,int>
#define inf (1<<30)
#define eps 1e-8
#define pb push_back
#define debug puts("=====")
using namespace std;
const int maxn=100005;
const ll mod=1000000007;
int n,m;
int f[55][55];
ll dp[2][2][2][2];
int main()
{
int cas=1;
int t;
int k,a;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
memset(f,0,sizeof(f));
for(int i=1;i<=m;i++) {
scanf("%d",&k);
while(k--) {
scanf("%d",&a);
f[i][a]=1;
}
}
ll ans=0;
for(int i=1;i<=n;i++) {
for(int j=i;j<=n;j++) {
for(int k=j;k<=n;k++) {
memset(dp,0,sizeof(dp));
int now=0;
dp[0][0][0][0]=1;
for(int e=1;e<=m;e++) {
memset(dp[now^1],0,sizeof(dp[now^1]));
for(int a=0;a<2;a++) {
for(int b=0;b<2;b++) {
for(int c=0;c<2;c++) {
dp[now^1][a][b][c]+=dp[now][a][b][c];
dp[now^1][a][b][c]%=mod;
dp[now^1][a^f[e][i]][b^f[e][j]][c^f[e][k]]+=dp[now][a][b][c];
dp[now^1][a^f[e][i]][b^f[e][j]][c^f[e][k]]%=mod;
}
}
}
now^=1;
}
if(i!=j && j!=k && i!=k) {
ans+=dp[now][1][1][1]*6;
ans%=mod;
}
else if(i==j && j==k) {
ans+=dp[now][1][1][1];
ans%=mod;
}
else {
ans+=dp[now][1][1][1]*3;
ans%=mod;
}
//cout<<i<<" "<<j<<" "<<k<<" "<<ans<<endl;
}
}
}
printf("Case #%d: %I64d\n",cas++,ans);
}
return 0;
}