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;
    }
  • 相关阅读:
    Vue之登录基础交互
    Vue之Slot用法初探
    序言
    sqlserver下通用 行转列 函数(原创)
    A printf format reference page (cheat sheet)
    [PowerShell]HTML parsing -- get information from a website
    [Python]打印a..z的字符
    Takari Extensions for Apache Maven (TEAM)
    【转】LAMBDAFICATOR: Crossing the gap from imperative to functional programming through refactorings
    [转][Java]使用Spring配合Junit进行单元测试的总结
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10627724.html
Copyright © 2011-2022 走看看