CF 1842 H

给自己的博客引流:3.15 解除密码 这个是这篇中最认真写的题。

妙妙题!!!太牛了。

首先,\(x_i\in [0,1]\),可以有两种:\(x_i<0.5,x_i\ge 0.5\)。因为在 \([0,1]\) 中抽出 \(0.5\) 的几率为 \(0\),就可以分成 \(x_i<0.5,x_i> 0.5\)。如果这样分,那么 \(x_i,x_j<0.5\implies x_i+x_j\le 1\)\(x_i,x_j>0.5\implies x_i+x_j\ge 1\)。因此我们只需要考虑 \(x_i<0.5,x_j>0.5\) 或者反过来的情况。为了方便起见,设 \(<0.5\) 为白色的,\(>0.5\) 为黑色的,默认 \(x_i\) 白色,\(x_j\) 黑色。

考虑一个白点和一个黑点怎么加起来 \(\le 1\)。几个解释是,黑色的到 \(1\) 的距离比白色的值大,即 \(1-x_j>x_i\)。如果加起来 \(\ge 1\),则 \(1-x_j<x_i\)。(如果 \(x_i>x_j\),则反过来)所以,我们可以求出 \(\min(x_i,1-x_i)\)\(\min(x_j,1-x_j)\) 的大小关系。我们可以小的向大的连边,形成一个图。

如果我们不考虑时间复杂度,那么我们想求出的是:

  • \(n\) 个点黑白染色。

  • 这种染色方案对应的图要是无环的,即有拓扑序。拓扑序是按照 \(\min(x_i,1-x_i)\) 的从小到大排序。

这个比较难求,我们可以反之求一个拓扑序,它对应的可行的黑白染色个数,设为 \(cnt\)。答案就是 \(\frac{cnt}{2^n\times n!}\)

\(dp_{msk}\) 为已经固定好了 \(msk\) 里面包含的数(作为 \(\min(x_i,1-x_i)\) 最小的 \(\texttt{popcnt}(msk)\) 个)的黑白染色方案数。怎么转移呢?我们还可以发现两个性质:

  • 如果 \(x_a+x_b\le 1\),则 \(\min(x_a,x_b)<0.5\)。也就是说,固定 \(\max(x_a,x_b)\) 对应的时候,\(\min\) 的已经在他前面了。

  • 如果 \(x_a+x_b\ge 1\),则 \(\max(x_a,x_b)>0.5\)。也就是说,固定 \(\min(x_a,x_b)\) 对应的时候,\(\max\) 的已经在他前面了。这是因为,\(\max\)\(\min(x_i,1-x_i)\) 这个值更小。

那么,就很好转移了。具体来说,对于所有 \(j\notin msk\)

  • 如果所有关于 \(j\)\(\le 1\) 的限制的另一端都确定了,\(j\) 就可以是黑色。

  • 如果所有关于 \(j\)\(\ge 1\) 的限制的另一端都确定了,\(j\) 就可以是白色。

时间复杂度 \(\mathcal{O}(2^nn)\)

Code
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const ll mod = 998244353;

ll pw(ll x,ll y=mod-2){
	ll res=1;
	while (y){
		if (y&1){
			res=res*x%mod;
		}
		x=x*x%mod;
		y>>=1;
	}
	return res;
}

ll msk[2][20],dp[1<<20];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	int n,m;
	cin>>n>>m;
	ll fac=1;
	for (ll i=1; i<=n; i++){
		fac=fac*i%mod;
	}
	ll div=pw(2,n)*fac%mod;
	for (int i=1; i<=m; i++){
		ll t,a,b;
		cin>>t>>a>>b;
		a--;
		b--;
		msk[t][a]|=1<<b;
		msk[t][b]|=1<<a;
	}
	dp[0]=1;
	for (int i=0; i<(1<<n); i++){
		for (int j=0; j<n; j++){
			if (!(i>>j&1)){
				if ((msk[0][j]|i)==i){
					(dp[i^(1<<j)]+=dp[i])%=mod;
				}
				if ((msk[1][j]|i)==i){
					(dp[i^(1<<j)]+=dp[i])%=mod;
				}
			}
		}
	}
	cout<<dp[(1<<n)-1]*pw(div)%mod<<"\n";
	return 0;
}
posted @ 2024-03-12 21:54  SFlyer  阅读(9)  评论(0编辑  收藏  举报