CF1326F2 Wise Men (Hard Version)

直接算不好算,考虑先算出超集和的答案,最后高维后缀差分求出原本的答案。

发现超集和的意义下的答案满足:将 (01) 串的连边关系构成图后,会得到若干条链,若两个 (01) 串得到的链长的可重集相同,则这两个 (01) 串的答案相等。因为答案是由全排列贡献的,所以有这个性质。

考虑直接枚举链长的可重集,也就是直接枚举 (n) 的整数拆分,(18) 的整数拆分只有 (P(18)=385),可以接受。可以通过 (DP) 求出 (g_{i,S}) 表示长度为 (i) 的链,链中的点为 (S) 的方案数。(dfs) 过程中用枚举到对应的链长后进行子集卷积即可,因为最后只用取全集的答案,所以这里可以用集合并卷积来代替子集卷积。

总复杂度为 (O((n^2+P(n))2^n))

#include<bits/stdc++.h>
#define maxn 20
#define maxm 262154
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,all;
int cnt[maxm];
ll f[maxm],g[maxn][maxm],h[maxn][maxm],v[maxn][maxm];
char w[maxn][maxn];
vector<int> ve;
map<vector<int>,ll> mp;
void dfs(int x,int pre,int sum)
{
	if(sum==n)
	{
		ll val=0;
		for(int i=0;i<all;++i) val+=v[x][i]*(cnt[i^(all-1)]&1?-1:1);
		mp[ve]=val;
		return;
	}
	for(int i=pre;i+sum<=n;++i)
	{
		for(int j=0;j<all;++j) v[x+1][j]=v[x][j]*g[i][j];
		ve.push_back(i),dfs(x+1,i,i+sum),ve.pop_back();
	}
}
int main()
{
	read(n),all=1<<n;
	for(int i=1;i<all;++i) cnt[i]=cnt[i>>1]+(i&1);
	for(int i=0;i<n;++i) scanf("%s",w[i]),h[i][1<<i]=1;
	for(int i=0;i<all;++i)
		for(int j=0;j<n;++j)
			for(int k=0;k<n;++k)
				if(!((i>>k)&1)&&w[j][k]=='1')
					h[k][i|(1<<k)]+=h[j][i];
	for(int i=0;i<all;++i)
		for(int j=0;j<n;++j)
			g[cnt[i]][i]+=h[j][i];
	for(int x=1;x<=n;++x)
		for(int len=1;len<all;len<<=1)
			for(int i=0;i<all;i+=len<<1)
				for(int j=i;j<i+len;++j)
					g[x][j+len]+=g[x][j];
	for(int i=0;i<all;++i) v[0][i]=1;
	dfs(0,1,0),all>>=1;
	for(int s=0;s<all;++s)
	{
		ve.clear();
		int pos;
		for(int i=0;i<n;i=pos+1)
		{
			pos=i;
			while(pos<n-1&&(s>>pos)&1) pos++;
			ve.push_back(pos-i+1);
		}
		sort(ve.begin(),ve.end()),f[s]=mp[ve];
	}
	for(int len=1;len<all;len<<=1)
		for(int i=0;i<all;i+=len<<1)
			for(int j=i;j<i+len;++j)
				f[j]-=f[j+len];
	for(int i=0;i<all;++i) printf("%lld ",f[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/lhm-/p/14586023.html