zoukankan      html  css  js  c++  java
  • P4336 [SHOI2016]黑暗前的幻想乡

    传送门

    答案=没有限制的方案数 - (限制1公司没修的方案 ∪ 限制2公司没修的方案 ∪ 限制3公司没修的方案 ∪...∪ 限制n-1公司没修的方案)

    矩阵树计算方案数,然后容斥

    根据容斥原理

    (限制1公司没修的方案 ∪ 限制2公司没修的方案 ∪ 限制3公司没修的方案 ∪...∪ 限制n-1公司没修的方案)

    =(所有限制一个公司没修的方案-所有限制两个公司没修的方案+所有限制三个公司没修的方案-所有限制四个公司没修的方案....)

    那么枚举数的二进制表示每个公司的参加情况然后计算贡献

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int mo=1e9+7;
    int n;
    ll G[27][27];
    struct edge{
        int x,y;
    };
    vector <edge> V[27];
    int Gauss()
    {
        ll ans=1;
        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
                while(G[j][i])
                {
                    ll t=G[i][i]/G[j][i];
                    for(int k=i;k<=n;k++)
                        G[i][k]=(G[i][k] - t*G[j][k])%mo;
                    swap(G[i],G[j]); ans=-ans;
                }
            ans=ans*G[i][i]%mo;
            if(!ans) return 0;
        }
        return (ans+mo)%mo;
    }
    int main()
    {
        n=read(); int a,x,y;
        for(int i=1;i<n;i++)
        {
            a=read();
            for(int j=1;j<=a;j++)
            {
                x=read(),y=read();
                V[i].push_back((edge){x,y});
            }
        }
        int ans=0,mx=(1<<n-1)-1;
        for(int i=0;i<=mx;i++)
        {
            int cnt=0; memset(G,0,sizeof(G));
            for(int j=1;j<n;j++)
                if((i>>j-1)&1)
                {
                    for(int k=V[j].size()-1;k>=0;k--)
                    {
                        x=V[j][k].x,y=V[j][k].y;
                        G[x][y]--; G[y][x]--;
                        G[x][x]++; G[y][y]++;
                    }
                    cnt++;
                }
            if((n-cnt)&1) ans=(ans+Gauss())%mo;
            else ans=(ans-Gauss()+mo)%mo;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    2018.5.22 Oracle安装配置在虚拟机中外部电脑连接服务
    2018.5.20 oracle强化练习
    2018.5.19 Oracle数据操作和管理表的综合练习
    2018.5.18 AndroidStudio创建项目出错
    2018.5.17 oracle函数查询
    2018.5.14 XML文档类型定义----DTD
    2018.5.13 oracle遇到的问题
    二元搜索算法(分治法)
    循环队列(弥补队列顺序储存的不足)
    队列的顺序储存
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10627724.html
Copyright © 2011-2022 走看看