hdu5117 Fluorescent DP,期望

題意: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章