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

    题面在这里!

        考虑容斥,我们可以求出用的建筑公司的集合至多是S的方案数(也就是最小生成树中的边只能用集合S内的建筑公司内的),这个跑一下矩阵树定理就好啦(注意可以有重边,因为一条边被不同公司建是算不同的方案的)。

        然后再容斥加加减减算一算就好啦。。。

        (神TM我一开始忘了去掉一行一列答案一直是0 。。。。)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int ha=1e9+7;
    
    inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
    
    inline int ksm(int x,int y){
    	int an=1;
    	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
    	return an;
    }
    
    int n,ci[25],ans,all;
    bool bt[200005];
    
    struct node{
    	int a[21][21];
    	
    	inline void clear(){ memset(a,0,sizeof(a));}
    	
    	node operator +(const node &b)const{
    		node r;
    		for(int i=1;i<=n;i++)
    		    for(int j=1;j<=n;j++) r.a[i][j]=add(a[i][j],b.a[i][j]);
    		return r;
    	}
    	
    	inline int Get(){
    		int an=1;
    		
    		for(int i=1,t,v;i<n;i++){
    			if(!a[i][i]) for(int j=i+1;j<n;j++) if(a[j][i]){
    				for(int k=i;k<n;k++) swap(a[j][k],a[i][k]);
    				an=ha-an; break;
    			}
    			an=an*(ll)a[i][i]%ha;
    			if(!an) break;
    			
    			t=ksm(a[i][i],ha-2);
    			for(int j=i+1;j<n;j++) if(a[j][i]){
    				v=t*(ll)a[j][i]%ha;
    				for(int k=i;k<n;k++) ADD(a[j][k],ha-a[i][k]*(ll)v%ha);
    		    }
    		}
    		
    		return an;
    	}
    }d[21],now;
    
    inline int solve(int S){
    	now.clear();
    	for(int i=1;i<n;i++) if(S&ci[i-1]) now=now+d[i];	
    	return bt[all^S]?ha-now.Get():now.Get();
    }
    
    int main(){
    	ci[0]=1;
    	for(int i=1;i<=20;i++) ci[i]=ci[i-1]<<1;
    	scanf("%d",&n),all=ci[n-1]-1;
    	for(int i=1;i<=all;i++) bt[i]=bt[i^(i&-i)]^1;
    	
    	for(int i=1,m,u,v;i<n;i++){
    		scanf("%d",&m);
    		while(m--){
    			scanf("%d%d",&u,&v);
    			ADD(d[i].a[u][u],1);
    			ADD(d[i].a[v][v],1);
    			ADD(d[i].a[u][v],ha-1);
    			ADD(d[i].a[v][u],ha-1);
    		}
    	}
    	
    	for(int i=1;i<=all;i++) ADD(ans,solve(i));
    	
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    Linux system basic 2 + add kernel for Jupyter
    Linux package installation: deb and rpm
    classification tips 01: npy file
    how to activate XMind8 to pro version.
    Linux system 初步
    try_except_finally
    Postgresql Json Sql
    python package install error and little code bugs
    小程序用户操作事件
    套数据操作步骤
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9284944.html
Copyright © 2011-2022 走看看