您的位置:首页 > 其它

HDU 5117 Fluorescent

2015-09-16 17:10 190 查看

题目描述:

Description

Matt, a famous adventurer who once defeated a pack of dire wolves alone, found a lost court. Matt finds that there are N fluorescent lights which seem to be the stars from the firmament. What’s more, there are M switches that control these fluorescent lights. Each switch is connected to a group of lights. When Matt touches a switch, all the lights connected to it will change their states (turning the dark on, turning the bright off).

Initially, all the fluorescent lights are dark. For each switch, Matt will touch it with probability 1 .

As a curious gentleman, Matt wants to calculate E[X3], where X represents the number of bright lights at the end, E[X3] represents the expectation of cube of X.

Input

The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains N, M (1 ≤ N, M ≤ 50), denoting the number of fluorescent lights (numbered from 1 to N ) and the number of switches (numbered from 1 to M ).

M lines follow. The i-th line begins with an integer Ki (1 ≤ K i ≤ N ). K i distinct integers l ij(1 ≤ l ij ≤ N ) follow, denoting the fluorescent lights that the i-th switch controls.

题解:

如果是求期望,那么因为期望的可加性,我们看每一个灯对答案的贡献,xi是0或者是1,有pi的概率,然后虽然是相关的,但是累加起来就好了.但是要求x^3的期望.我们把表达式写出来:先是EX的表达式:EX*2^m = (所有情况遍历)(x1+…+xn).因为期望的可加性,EX=(遍历n)(1*pi). 显然E(X^3)不能EX直接三次方.因为E(x^3)的含义是在某种情况下,把signma(x1+…+xn)搞一个三次方,之后的期望.因此我们把(signma(x1+…+xn))^3拆开.之后就有加法啦.然后利用期望的线性可加性就好算了.对于比如x1*x2*x3这种,显然都是1才有意义,那么我们需要计算都是1一共有多少种情况数.可以用dp[s]表示当前三个灯的状态,这样不用关注另外的灯的状态了.其实有一个小技巧,直接枚举三次1~n,不管ijk是谁,直接来一次就好了.具体看代码.

重点:

(1)期望的线性可加性:先利用指示器的思路把每一个变量的贡献写出来,然后写出期望的表达式,不好写就写出所有情况的和的形式.然后研究拆开成几个部分的加法,之后单独考虑加法就行了.

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>

using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll g[51],f[51][8],ans;
int n,m;
void solve()
{
scanf("%d%d",&n,&m);
//printf("%d %d\n",n,m);
memset(g,0,sizeof g);
ans = 0;
for (int i = 1;i <= m;i++)
{
int num;
scanf("%d",&num);
for (int j = 1;j <= num;j++)
{
int x;
scanf("%d",&x);
g[i] |= (1ll << x);
}
}
for (int i = 1;i <= n;i++)
for (int j = 1;j <= n;j++)
for (int k = 1;k <= n;k++)
{
memset(f,0,sizeof f);
f[0][0] = 1;
for (int no = 1;no <= m;no++)
for (int st = 0;st < (1<<3);st ++)
{
f[no][st] = (f[no][st] + f[no-1][st]) % mod;
int mask = 0;
if (g[no] & (1ll<<i)) mask |= 1;
if (g[no] & (1ll<<j)) mask |= 2;
if (g[no] & (1ll<<k)) mask |= 4;
//printf("%d %I64d\n",no,mask);
for (int stp = 0;stp < (1<<3);stp ++)
if ((stp ^ mask) == st)
{

f[no][st] = (f[no][st] + f[no-1][stp]) % mod;
}
}
//printf("%I64d\n",f[m][8]);
ans = (ans + f[m][7]) % mod;
}
static int ca = 0;
printf("Case #%d: %I64d\n",++ca,ans);
}
int main()
{
// freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while (t--)
solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: