题目大意:
n个灯,m个开关,每个开关能控制一些灯的状态,即关闭的打开,打开的关闭。一开始灯全部是关闭的。现在有个人去操作这些开关。现在问这个人操作完这些开关后,亮着的灯的期望E(x),但是题目要求输出的是E(x^3)*2^m%(1e9+7)。
解题思路:m个开关,显然会2^m次组合首先考虑求E(x)。显然就是将这2^m种开关的开闭组合求出来每种情况的灯亮着的个数和sum(x),然后sum(x)/(2^m)就是E(x)。考虑在这2^m次中,每栈灯的贡献。
dp[i][j]表示前j个开关能将第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的状态压缩起来。
然后求解贡献的思路就和上面一样了。
对于x=a1+a2+……+an ,ai 代表第i栈灯亮与不亮的情况。始终不理解 。分解成三个for循环也不太理解为什么最后一定是这三个灯都亮着的情况dp[7][m];
这个题可以算是看到现在最有意思的题了,再就是数据可能是long long型,1ll<<x看了好久。。一直以为是三个一,很是懵。。。后来问同学才知道是一个一,两个L,代表long long型。。不过这几个处理还不是特别明白~sum(x)可以想象,sum(x^3),得继续在看看、
代码:
#include<bits/stdc++.h>
#define F(i,a,b) for(int i=(a);i<=(b);++i)
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=57,P=1e9+7;
int t,n,m,ans,cas,dp[8][N],num,x;
ll sw[N];
void up(int &a,int b){a+=b;if(a>=P)a-=P;}
int main(){
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m),mst(sw,0),ans=0;
F(i,1,m)
{
scanf("%d",&num);
F(j,1,num)scanf("%d",&x),sw[i]|=1ll<<x;
}
F(i,1,n)F(j,1,n)F(k,1,n)
{
mst(dp,0);
dp[0][0]=1;
F(l,0,m-1)F(u,0,7)if(dp[u][l])
{
int nxt=u;
if(sw[l+1]&(1ll<<i))nxt^=1;
if(sw[l+1]&(1ll<<j))nxt^=2;
if(sw[l+1]&(1ll<<k))nxt^=4;
up(dp[nxt][l+1],dp[u][l]);//开
up(dp[u][l+1],dp[u][l]);//关
}
up(ans,dp[7][m]);
}
printf("Case #%d: %d\n",++cas,ans);
}
return 0;
}