• HDU


    原题链接

    题意

    有N个灯和M个开关,每个开关控制着一些灯,如果按下某个开关,就会让对应的灯切换状态;问在每个开关按下与否的一共2^m情况下,每种状态下亮灯的个数的立方的和。

    思路
    1、首先注意到N<=50,M<=50,因此很容易想到状压;

    2、考虑X^3,其中X就是每种状况下亮着的灯的数量;

    3、如何解这个X^3?我们把它展开——
    X=x1+x2+x3+...+xn,其中xi是第i个灯的亮或暗状况;
    因此X^3=(x1+x2+x3+...+xn)*(x1+x2+x3+...+xn)*(x1+x2+x3+...+xn)=Σxi*xj*xk (1<=i<=j<=k<=n);

    4、dp[m][state]代表前m个开关,达成状态为state的方案数,其中state从(000)2~(111)2,代表三个灯的亮或灭;在其基础上dp就行了;遍历i,j,k,同时将开关的控制状态压缩。

    5、答案每次加上dp[m][7],因为只有xi=xj=xk=1时,才对X^3有贡献,总复杂度O(n^3*m);

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define ll long long
    #define ull unsigned long long
    #define LOCAL
    
    using namespace std;
    const int maxn=1e5+10;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    
    ll d[51][8];
    ll s[51];
    
    int main(){
        int t,n,m,num;
        cin>>t;
        for(int kase=1;kase<=t;kase++){
            memset(s,0,sizeof(s));
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++){
                scanf("%d",&num);
                for(int j=1;j<=num;j++){
                    int t;
                    scanf("%d",&t);
                    s[i]|=(1LL<<t);///状压
                }
            }
            ll ans=0;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    for(int k=1;k<=n;k++){
                        memset(d,0,sizeof(d));
                        d[0][0]=1;
                        for(int x=1;x<=m;x++){
                            for(int y=0;y<8;y++){
                                int t=y;
                                if(s[x]&(1LL<<i)) t^=1;
                                if(s[x]&(1LL<<j)) t^=2;
                                if(s[x]&(1LL<<k)) t^=4;
                                d[x][y]+=d[x-1][y];
                                d[x][t]+=d[x-1][y];
                            }
                        }
                        ans=(ans+d[m][7])%mod;
                    }
                }
            }
            printf("Case #%d: %lld
    ",kase,ans);
        }
        return 0;
    }
  • 相关阅读:
    日期格式化
    堆栈
    编写自己的C头文件
    线性表(gcc实现)
    排序的稳定性
    git创建和合并分支
    当单选input框改变时触发
    css样式定义
    div块显示在一行
    redis数据结构(一)
  • 原文地址:https://www.cnblogs.com/fht-litost/p/7265723.html
Copyright © 2020-2023  润新知