其他分享
首页 > 其他分享> > 20201009校测

20201009校测

作者:互联网

国庆长假终于结束了

T1

太水了,跳过

T2

description:

给出一张n个点m条边的有向图,问其中有多少边的子集使得不存在任意一个环

data range:

\(N\le 17\)

solution:

巨佬题解

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=17,mod=1e9+7;
int n,m,pw[N*N];
int g[N+5][1<<N],num[1<<N],lg2[1<<N],dp[1<<N],tmp[1<<N];
inline int ct(int x)
{
	int ans=0;
	for(int i=0;(1<<i)<=x;++i)
		if(x&(1<<i))++ans;
	return ans;
}
inline int sig(int x){return (x&1)?-1:1;}
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
int main()
{
	scanf("%d%d",&n,&m);int M=1<<n;
	for(int i=1;i<=m;++i)
	{
		int u,v;scanf("%d%d",&u,&v);
		for(int j=0;j<M;++j)
			if(j&(1<<(v-1)))++g[u][j];
	}
	pw[0]=1;for(int i=1;i<=m;++i)pw[i]=2ll*pw[i-1]%mod;
	for(int i=0;i<M;++i)num[i]=ct(i);
	for(int i=1;i<=n;++i)lg2[1<<(i-1)]=i;
	dp[0]=1;
	for(int zt=0;zt<M;++zt)
	{
		int bu=(M-1)^zt;
		for(int j=bu;j;j=(j-1)&bu)
		{
			int s=bu^((j-1)&bu),lst=s&(-s);
			tmp[s]=tmp[s^lst]+g[lg2[lst]][zt];
			if(sig(num[s]+1)==1)dp[zt|s]=add(dp[zt|s],1ll*pw[tmp[s]]*dp[zt]%mod);
			else dp[zt|s]=dec(dp[zt|s],1ll*pw[tmp[s]]*dp[zt]%mod);
		}
	}
	cout<<dp[M-1];
	return 0;
}

标签:有向图,17,int,题解,20201009,long,校测,mod
来源: https://www.cnblogs.com/zmyzmy/p/13788651.html