• SHOI2016 黑暗前的幻想乡


    题目链接:戳我

    幻想乡是个什么东西??(逃

    矩阵树定理+容斥

    就是设(dp[i])表示至多i个公司修建道路,那么我们有(ans=dp[n-1]-dp[n-2]+dp[n-3]......)balabala(就是那个容斥公式嘛qwqwq)

    然后每次都跑一次矩阵树定理qwqwq

    但是这样的时间复杂度是(O(n^32^{n-1}))???所以说。。。跑的。。。2s。。。很勉强qwqwq

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define MAXN 100010
    #define mod 1000000007
    using namespace std;
    int n,maxx,ans;
    int cnt[MAXN],dp[20][20];
    struct Node{int x,y;};
    vector<Node>node[20];
    inline int getnum(int x)
    {
    	int cur_ans=0;
    	for(int i=0;i<=21;i++)
    		if(x&(1<<i))
    			cur_ans++;
    	return cur_ans;
    }
    inline int matrix_tree()
    {
    	int cur_ans=1;
    	for(int i=2;i<=n;i++)
    	{
    		for(int j=i+1;j<=n;j++)
    		{
    			while(dp[j][i])
    			{
    				int t=dp[i][i]/dp[j][i];
    				for(int k=i;k<=n;k++)
    					dp[i][k]=(dp[i][k]-1ll*dp[j][k]*t%mod+mod)%mod;
    				swap(dp[i],dp[j]);
    				cur_ans=(-cur_ans+mod)%mod;
    			}
    		}
    		cur_ans=(1ll*cur_ans*dp[i][i])%mod;
    	}
    	return cur_ans;
    }
    inline int calc(int x)
    {
    	memset(dp,0,sizeof(dp));
    	for(int i=1;i<n;i++)
    	{
    		if(x&(1<<(i-1)))
    		{
    			for(int j=0;j<node[i].size();j++)
    			{
    				int u=node[i][j].x,v=node[i][j].y;
    				dp[u][u]=(dp[u][u]+1)%mod;
    				dp[v][v]=(dp[v][v]+1)%mod;
    				dp[u][v]=(dp[u][v]-1+mod)%mod;
    				dp[v][u]=(dp[v][u]-1+mod)%mod;
    			}
    		}
    	}
    	return matrix_tree();
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	freopen("ce.out","w",stdout);
    	#endif
    	scanf("%d",&n);
    	maxx=(1<<n-1)-1;
    	for(int i=1;i<n;i++)
    	{
    		int k,u,v;
    		scanf("%d",&k);
    		for(int j=1;j<=k;j++)
    		{
    			scanf("%d%d",&u,&v);
    			node[i].push_back((Node){u,v});
    		}
    	}
    	for(int i=0;i<=maxx;i++) cnt[i]=getnum(i);
    	for(int i=0;i<1<<(n-1);++i) 
    		ans=(ans+(((n-1-cnt[i])&1)?mod-calc(i):calc(i)))%mod;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    比较两个日期的大小(年月日)
    js闭包
    星星点点
    刮刮卡刮奖效果
    html图片自适应屏幕大小(手机)
    将博客搬至CSDN
    类的讲义
    Anaconda教程
    css基础
    javascript
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10429756.html
Copyright © 2020-2023  润新知