1. 程式人生 > >hdu 5117 Fluorescent(狀壓dp+思維)

hdu 5117 Fluorescent(狀壓dp+思維)

closed bsp 貢獻 ide 開關 play 壓縮 全部 求解

題目鏈接:hdu 5117 Fluorescent

題意:

有n個燈,m個開關,每個開關能控制一些燈的狀態,即關閉的打開,打開的關閉。一開始燈全部是關閉的。

現在有個人去操作這些開關,顯然會有2^m次組合。

現在問這個人操作完這些開關後,亮著的燈的期望E(x)

但是題目要求輸出的是E(x^3)*2^m%(1e9+7)。

題解:

首先我們先來考慮求E(x)。

顯然就是將這2^m種開關的開閉組合求出來每種情況的燈亮著的個數和sum(x),

然後sum(x)/(2^m)就是E(x)。

這個怎麽求呢。

考慮在這2^m次中,每棧燈的貢獻。

考慮dp[i][j][2],表示前j個開關能將第i棧燈開啟和關閉的方案數。

那麽dp[i][j][1]就是第i棧燈的貢獻。

現在考慮求E(x^3)*2^m。

顯然就是就那個sum(x^3)。

設x=a1+a2+……+an ,ai 代表第i棧燈亮與不亮的情況。

那麽x^3=(a1+a2+……+an)*(a1+a2+……+an)*(a1+a2+……+an)。

展開就是Σ(ai*aj*ak )。

所以我們考慮枚舉i,j,k,然後將i,j,k的狀態壓縮起來。

然後求解貢獻的思路就和上面一樣了。

技術分享
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 3 #define
mst(a,b) memset(a,b,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 7 const int N=57,P=1e9+7; 8 int t,n,m,ans,cas,dp[8][N],num,x; 9 ll sw[N]; 10 11 void up(int &a,int b){a+=b;if(a>=P)a-=P;} 12 13 int main(){ 14 scanf("%d",&t); 15 while(t--) 16 { 17 scanf("
%d%d",&n,&m),mst(sw,0),ans=0; 18 F(i,1,m) 19 { 20 scanf("%d",&num); 21 F(j,1,num)scanf("%d",&x),sw[i]|=1ll<<x; 22 } 23 F(i,1,n)F(j,1,n)F(k,1,n) 24 { 25 mst(dp,0); 26 dp[0][0]=1; 27 F(l,0,m-1)F(u,0,7)if(dp[u][l]) 28 { 29 int nxt=u; 30 if(sw[l+1]&(1ll<<i))nxt^=1; 31 if(sw[l+1]&(1ll<<j))nxt^=2; 32 if(sw[l+1]&(1ll<<k))nxt^=4; 33 up(dp[nxt][l+1],dp[u][l]);// 34 up(dp[u][l+1],dp[u][l]);// 35 } 36 up(ans,dp[7][m]); 37 } 38 printf("Case #%d: %d\n",++cas,ans); 39 } 40 return 0; 41 }
View Code

hdu 5117 Fluorescent(狀壓dp+思維)