• P6846[CEOI2019]Amusement Park【状压dp,FWT】


    正题

    题目链接:https://www.luogu.com.cn/problem/P6846


    题目大意

    给出\(n\)个点\(m\)条边的一张有向图,保证两个点之间最多只有一条边。现在你可以取反一些边使得图变为一张\(DAG\),求所有方案的取反的边数和。

    \(1\leq n\leq 18\)


    解题思路

    考虑到对于一种方案取反所有边就是另一种方案,所以每种方案的取反边数的平均值肯定是\(\frac{m}{2}\),所以我们只需要统计方案数就好了。

    然后再考虑\(dp\),朴素的做法是\(O(3^n)\)的,记\(G_S\)表示集合\(S\)是否是独立集那么有

    \[F_S=\sum_{T\sube S}(-1)^{|T|+1}F_{S-T}G_T \]

    然后化成集合幂级数的形式就是

    \[F=FG+1\Rightarrow F=\frac{1}{1-G} \]

    至于集合幂级数怎么求逆,定义占位多项式

    \[G'_{S,i}=\sum_{S=0}^n[count(S)=i]G_S \]

    然后对于每个\(G_S\)视为一个多项式求逆。

    然后求逆可以用\(O(n^2)\)的反正\(n\)很小。

    对于\(a\)求逆,首先有\(a^{-1}[x_0]=\frac{1}{a[x_0]}\),然后有

    \[\sum_{i=0}^na[x^i]a^{-1}[x^{n-i}]=0\Rightarrow a^{-1}[x^n]=\frac{\sum_{i=0}^{n-1}a^{-1}[x^i]a[x^{n-i}]}{a[x^0]} \]

    这样就可以\(O(n^2)\)递推了。

    时间复杂度:\(O(2^nn^2)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=18,P=998244353;
    ll n,m,MS,c[1<<N],g[1<<N],F[N+1][1<<N],G[N+1],H[1<<N];
    void FWT(ll *f,ll op){
    	for(ll p=2;p<=MS;p<<=1)
    		for(ll k=0,len=p>>1;k<MS;k+=p)
    			for(ll i=k;i<k+len;i++)
    				(f[i+len]+=f[i]*op+P)%=P;
    	return;
    }
    signed main()
    {
    	scanf("%lld%lld",&n,&m);
    	for(ll i=1,x,y;i<=m;i++){
    		scanf("%lld%lld",&x,&y);
    		x--;y--;g[(1<<x)|(1<<y)]=1;
    	}
    	MS=(1<<n);
    	for(ll i=0;i<n;i++)
    		for(ll s=0;s<MS;s++)
    			if(!((s>>i)&1))g[s^(1<<i)]|=g[s];
    	for(ll i=1;i<MS;i++){
    		c[i]=c[i-(i&-i)]+1;
    		if(!g[i])F[c[i]][i]=(c[i]&1)?1:(P-1);
    	}
    	F[0][0]=1;
    	for(ll i=0;i<=n;i++)FWT(F[i],1);
    	for(ll s=0;s<MS;s++){
    		for(ll i=0;i<=n;i++)F[i][s]=P-F[i][s];
    		G[0]=1;
    		for(ll i=1;i<=n;i++){
    			G[i]=0;
    			for(ll j=1;j<=i;j++)
    				(G[i]+=P-G[i-j]*F[j][s]%P)%=P;
    		}
    		H[s]=G[n];
    //		printf("%lld ",G[n]);
    	}
    	FWT(H,-1);
    	printf("%lld\n",(P+1)/2*H[MS-1]%P*m%P);
    	return 0;
    }
    
  • 相关阅读:
    GNU make manual 翻译( 一百五十)
    [导入]Google开发者日见闻 王开源现身
    [导入]微软中国原高管宫力就任火狐中国总经理
    [导入]QQTalk Beta1 简体中文版
    [导入]《南方都市报》:国产龙芯产业化 难
    [导入][多图]Nokia正式发布奢华8600/6500双子手机
    [导入]用户界面设计的技巧与技术
    [导入]BitComet(比特彗星) 0.89
    [导入]µTorrent 1.7 beta 2248
    今天我注册了
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15437650.html
Copyright © 2020-2023  润新知