zoukankan      html  css  js  c++  java
  • 「SHOI 2016」黑暗前的幻想乡

    题目链接

    戳我

    (Describe)

    (n−1)个公司,每个公司能修一些边,求每条边都让不同的公司来修的生成树的方案数

    (Solution)

    这道题很明显容斥.答案就是:所有都选的生成树个数(-)一个没选的生成树个数(+)两个没选的生成树个数(-...)

    至于生成树个数怎么算,用(Matrix - Tree)矩阵树定理做就好了
    如果不会:传送门

    (Code)

    #include<bits/stdc++.h>
    #define int long long
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    const int mod=1e9+7;
    int read(){
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    int a[21][21],len[1001],f[1001][1001],vis[1001][1001],n,ans,bj[10001];
    void init(){
    	memset(a,0,sizeof(a));
        for(int i=1;i<n;i++)
            if(bj[i])
                for(int j=1;j<=len[i];j++)
                    ++a[f[i][j]][f[i][j]],++a[vis[i][j]][vis[i][j]],--a[f[i][j]][vis[i][j]],--a[vis[i][j]][f[i][j]];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                a[i][j]=(a[i][j]+mod)%mod;
    }
    int ksm(int a,int b){
    	int ans=1;
    	while(b){
    		if(b&1)
    			ans=ans*a%mod;
    		a=a*a%mod;
    		b>>=1;
    	}
    	return ans;
    }
    int work(){
    	init();
    	int js=1;
        for(int i=2;i<=n;i++){
    		int inv=ksm(a[i][i],mod-2);
            for(int j=i+1;j<=n;j++)
                while(a[j][i]){
                    int x=a[j][i]*inv%mod;
                    for(int k=i;k<=n;k++)
                        a[j][k]=(a[j][k]-x*a[i][k]%mod+mod)%mod,swap(a[i][k],a[j][k]);
                }
            js=js*a[i][i]%mod;
        }
        return js%mod;
    }
    void dfs(int x,int opt){
        if(x==n){
    		(opt&1)?ans-=work():ans+=work(),ans=(ans+mod)%mod;
            return;
        }
        bj[x]=1;dfs(x+1,opt),bj[x]=0;dfs(x+1,opt+1);
    }
    main(){
    	n=read();
    	for(int i=1;i<n;i++){
    		len[i]=read();
    		for(int j=1;j<=len[i];j++)
    			f[i][j]=read(),vis[i][j]=read();
    	}
    	dfs(1,0);
    	printf("%lld",ans);
    }
    
  • 相关阅读:
    大二下-个人课堂总结
    第十六周总结
    第十五周总结
    计算最长英语单词链
    第十四周总结
    大道至简阅读笔记03
    信息反馈—冲刺20
    sudo安装某一文件报错:E: 无法获得锁 /var/lib/dpkg/lock
    linux脚本文件执行的方法之间的区别
    opencv的安装及填坑
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10332490.html
Copyright © 2011-2022 走看看