ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

UOJ #37. 【清华集训2014】主旋律

2022-08-03 17:36:29  阅读:148  来源: 互联网

标签:S2 37 枚举 UOJ 2014 define 转移 dp mod


题面传送门

首先我们发现对强连通图不太好计数,那么我们对不要求弱联通的非强连通图计数会好做一点,然后用所有的方案减去即可。

容易发现这样的图缩点以后是一个DAG,则可以参照DAG计数的方法,每次枚举入度为\(0\)的点。具体的,我们设\(dp_{S1,S2}\)表示\(S1\)导出子图中入度为\(0\)的点为\(S2\)的方案数。则每次枚举新的入度为\(0\)的点是,每个之前入度为\(0\)的点一定要向现在\(0\)入度的点有一条边。其余边随意即可。但是这样复杂度是\(O(4^n)\)的过不去。

我们考虑进一步容斥:枚举一个子集\(S2\),表示这中间有\(i\)个强连通分量且互相没有边的方案数记为\(g_{S2,i}\),则\(dp\)每次枚举一个\(g_{S2,i}\)转移,但是我们并不能保证只有\(i\)个无入度的点。因此要乘上容斥系数\((-1)^{i+1}\)来转移。这样的转移之前的边就可以任选。\(g\)的转移强制包含最大的点即可不算重。复杂度降到了\(O(3^nn^2)\)。然后获得了和暴力同分的好成绩

发现瓶颈在于数两个点集之间的边数,容易位运算优化,做到\(O(3^nn)\)。

理论上这东西其实是可以跑的,但是常数实在有点大。因此我们考虑\(g\)的转移,有经典优化:每次转移乘上\(-1\),即可将\((-1)^{i+1}\)同步转移,不用记录后面一维。\(dp\)的转移也不用枚举了。常数得到大大优化。

另外其实统计边数还可以用bitset进一步优化至\(O(\frac{M3^n}{w})\),\(w=64\)但没必要。

code:

#include<bits/stdc++.h>
#define I inline
#define ll long long
#define db double
#define lb long db
#define N (15+5)
#define M ((1<<15)+5)
#define K (1500+5)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-5)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,Fl[N][N],Fs[N],lg[M],H[M];ll Po[N*N],dp[M],g[M],W[M],P[N];
int main(){
	freopen("1.in","r",stdin);
	int i,j,x,y,z,h;scanf("%d%d",&n,&m);k=(1<<n);for(i=1;i<=m;i++) scanf("%d%d",&x,&y),Fl[x-1][y-1]=1,Fs[x-1]|=(1<<y-1);for(Po[0]=i=1;i<=m;i++) Po[i]=Po[i-1]*2%mod;
	for(i=2;i<k;i++) lg[i]=lg[i/2]+1;for(i=1;i<k;i++)H[i]=H[i>>1]+(i&1);for(i=1;i<(1<<n);i++){
		z=lg[i];W[i]=W[i^(1<<z)];for(j=0;j<z;j++) i>>j&1&&(W[i]+=Fl[z][j]+Fl[j][z]);
		for(j=i&(i-1);j>(i^j);j=(j-1)&i) g[i]=(g[i]+(mod-g[i^j])*(Po[W[j]]-dp[j]+mod))%mod;
		for(j=i;j;j=(j-1)&i){
			int Ct=0;x=j;while(x) Ct+=H[Fs[lg[x&-x]]&(i^j)],x^=x&-x;
			dp[i]=(dp[i]+Po[Ct+W[i^j]]*g[j])%mod;
		}
		g[i]=(g[i]+Po[W[i]]-dp[i]+mod)%mod;
	}printf("%lld\n",(Po[W[k-1]]-dp[k-1]+mod)%mod);
}

标签:S2,37,枚举,UOJ,2014,define,转移,dp,mod
来源: https://www.cnblogs.com/275307894a/p/16547921.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有