• P4336 [SHOI2016]黑暗前的幻想乡


    终于下定决心搞一下高斯消元了,打完模板就尝试来做一下这道题,发现一下子就秒掉了?

    题解

    直接考虑容斥加矩阵树定理,令 (U) 为工程队的全集,考虑强制令集合 (S) 中的建筑队不修路,(f(S)) 表示此方案下的生成树个数,则答案为

    [ans=sum_{Ssubseteq U} (-1)^{|S|}cdot f(S) ]

    (f(S)) 就直接通过矩阵树定理求。时间复杂度是 (O(n^32^n)) ,好像可以通过?

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=20;
    const int MOD=1e9+7;
    int n,a[N][N],b[N][N],res=0;
    vector<pair<int,int> > bag[N];
    int ksm(int x,int k){
    	int res=1;
    	for(;k;k>>=1,x=x*x%MOD)
    	if(k&1) res=res*x%MOD;
    	return res;
    }
    void dfs(int now,int cnt){
    	if(now>=n){
    		for(int i=1;i<n;++i){
    			for(int j=1;j<n;++j)
    			b[i][j]=a[i][j];
    		}
    		for(int i=1;i<n;++i){
    			for(int j=1;j<n;++j){
    				if(i==j) continue;
    				int del=b[j][i]*ksm(b[i][i],MOD-2)%MOD;
    				for(int k=1;k<n;++k) b[j][k]+=MOD-del*b[i][k]%MOD,b[j][k]%=MOD;
    			}
    		}
    		int sum=pow(MOD-1,cnt%2);
    		for(int i=1;i<n;++i) sum*=b[i][i],sum%=MOD;
    		res+=sum,res%=MOD;
    		return ;
    	}
    	dfs(now+1,cnt+1);
    	for(int i=0;i<(int)bag[now].size();++i){
    		a[bag[now][i].first][bag[now][i].second]+=MOD-1;
    		a[bag[now][i].first][bag[now][i].second]%=MOD;
    		a[bag[now][i].second][bag[now][i].first]+=MOD-1;
    		a[bag[now][i].second][bag[now][i].first]%=MOD;
    		a[bag[now][i].first][bag[now][i].first]++;
    		a[bag[now][i].first][bag[now][i].first]%=MOD;
    		a[bag[now][i].second][bag[now][i].second]++;
    		a[bag[now][i].second][bag[now][i].second]%=MOD;
    	}
    	dfs(now+1,cnt);
    	for(int i=0;i<(int)bag[now].size();++i){
    		a[bag[now][i].first][bag[now][i].second]++;
    		a[bag[now][i].first][bag[now][i].second]%=MOD;
    		a[bag[now][i].second][bag[now][i].first]++;
    		a[bag[now][i].second][bag[now][i].first]%=MOD;
    		a[bag[now][i].first][bag[now][i].first]+=MOD-1;
    		a[bag[now][i].first][bag[now][i].first]%=MOD;
    		a[bag[now][i].second][bag[now][i].second]+=MOD-1;
    		a[bag[now][i].second][bag[now][i].second]%=MOD;
    	}
    }
    signed main(){
    	cin>>n;
    	for(int i=1;i<n;++i){
    		int m,u,v;scanf("%lld",&m);
    		for(int j=1;j<=m;++j){
    			scanf("%lld %lld",&u,&v);
    			bag[i].push_back(make_pair(u,v));
    		}
    	}
    	dfs(1,0),printf("%lld
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    (数论选拔)联盟阵容
    ai变成bi(递增)最小次数
    状压dp
    dp被3整除的子序列
    离散化+莫队
    dp+哈希
    set的应用
    NOIP 2016 明明的随机数
    洛谷背景更改
    zzulioj 1734 堆
  • 原文地址:https://www.cnblogs.com/Point-King/p/14359038.html
Copyright © 2020-2023  润新知