首页 > 其他分享 >【CF1292F】Nora's Toy Boxes(状压DP)

【CF1292F】Nora's Toy Boxes(状压DP)

时间:2022-10-31 20:02:15浏览次数:67  
标签:连通 Toy return int 类点 状压 fa Boxes mod

考虑将点分为 $A,B$ 两类。其中 $[x\in A]\iff\exists_{y\neq x},y|x$。

那么我们删去的点只可能在 $B$ 类中,且当前 $x\in B$ 可删当且仅当存在 $y\in B,z\in A$ 使得 $z|x\land z|y$。

那么对于 $z\in A,x\in B,z|x$,连边 $(z,x)$。这样得到一个二分图,每次删除操作相当于选择某个 $z\in A$ 且 $z$ 的度数 $\geq 2$,然后删去某个和 $z$ 相邻的点。

对二分图中每个连通块单独考虑,假设该连通块 $B$ 类有 $m$ 个点,那么发现答案能达到上界 $m-1$:以某个 $B$ 类点开始跑一棵生成树,然后从叶子往根删即可。

现在考虑统计方案数。只需统计单个连通块内的方案数,然后连通块间乘个组合数即可。

发现连通块内能删到上界的等价条件是:每次删完某个 $B$ 类点后,剩下的 $B$ 类点仍然是连通的。进一步地,若我们枚举最后剩下的是哪个 $B$ 类点 $lst$,我们只需保证当前所有未删的 $B$ 类点都与 $lst$ 连通即可。

数据范围提示我们可能是指数级做法。那么先挖掘到一条可能有用的性质:$A$ 类点至多 $20$ 个,因为 $>20$ 的 $A$ 类点至多有 $1$ 条邻边,那么它是没用的。

进一步地,由于 $x,2x$ 不可能同时成为 $A$ 类点,所以现在有用的 $A$ 类点至多 $10$ 个。同时这也是紧界:考虑 $A$ 类点为 $11,12,\cdots,20$。

把删点变成加点,虽然是等价的,但是会直观很多,且助于思考。

考虑 DP。发现我们可以只关注 $A$ 类点的添加过程(具体来说,是 $A$ 类点在 $B$ 类点添加序列的什么位置变化了,且变化是什么),而通过组合数算出 $B$ 类点的添加方案数。可以做到时间复杂度 $O(n2^{n/6})$。

#include<bits/stdc++.h>

#define N 65

using namespace std;

namespace modular
{
	const int mod=1000000007;
	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;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
	inline void Add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
	inline void Dec(int &x,int y){x=x-y<0?x-y+mod:x-y;}
	inline void Mul(int &x,int y){x=1ll*x*y%mod;}
	inline int poww(int a,int b){int ans=1;for(;b;Mul(a,a),b>>=1)if(b&1)Mul(ans,a);return ans;}
}using namespace modular;

int n,a[N],fa[N];
int fac[N],ifac[N];
bool AB[N],vis[N];

int find(int x)
{
	return x==fa[x]?x:(fa[x]=find(fa[x]));
}

pair<int,int> solve(int rt)
{
	static int f[1050],w[1050],from[N];
	vector<int> A,B;
	for(int i=1;i<=n;i++)
		if(find(i)==rt) (AB[i]?B:A).push_back(a[i]),vis[i]=1;
	while(!A.empty()&&A.back()>20) A.pop_back();
	int maxn=(1<<A.size())-1;
	memset(f,0,sizeof(int)*(maxn+1));
	for(int i=0;i<B.size();i++)
	{
		from[i]=0;
		for(int j=0;j<A.size();j++)
			if(!(B[i]%A[j])) from[i]|=(1<<j);
	}
	for(int S=0;S<=maxn;S++)
	{
		w[S]=0;
		for(int j=0;j<B.size();j++)
			if((from[j]&S)==from[j]) w[S]++;
	}
	for(int i=0;i<B.size();i++)
		Add(f[from[i]],mul(fac[B.size()-1],ifac[B.size()-w[from[i]]]));//C(B-1,w[from[i]]-1)*fac[w[from[i]-1]]
	for(int S=0;S<maxn;S++)
	{
		if(!f[S]) continue;
		for(int j=0;j<B.size();j++)
		{
			if((S&from[j])&&((S&from[j])!=from[j]))
			{
				int T=S|from[j];
				Add(f[T],mul(mul(fac[B.size()-w[S]-1],ifac[B.size()-w[T]]),f[S]));
				//C(x,y)*fac[y]
			}
		}
	}
	return make_pair(B.size()-1,f[maxn]);
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
		for(int j=1;j<i;j++)
			if(!(a[i]%a[j])){AB[i]=1;continue;}
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=n;i++)
		if(!AB[i]) for(int j=i+1;j<=n;j++)
			if(!(a[j]%a[i])) fa[find(i)]=find(j);
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
	ifac[n]=poww(fac[n],mod-2);
	for(int i=n;i>=1;i--) ifac[i-1]=mul(ifac[i],i);
	int ans=1,s=0;
	for(int i=1;i<=n;i++)
	{
		if(AB[i]&&find(i)==i&&!vis[i])
		{
			auto pr=solve(i);
			Mul(ans,mul(pr.second,ifac[pr.first]));
			s+=pr.first;
		}
	}
	Mul(ans,fac[s]);
	printf("%d\n",ans);
	return 0;
}

标签:连通,Toy,return,int,类点,状压,fa,Boxes,mod
From: https://www.cnblogs.com/ez-lcw/p/16845549.html

相关文章

  • 【XSY3896】相似(dp套dp,状压)
    题面相似题解可以发现,\(S\)和\(T\)相似,等价于它们的最长公共子序列长度至少为\(n-k\)。首先考虑如何求出两个字符串的\(\text{LCS}\)(最长公共子序列)。考虑dp:......
  • 【XSY3513】Multiple of Nine(状压DP)
    题意:转化后变为:给一张\(n\)个点的图,你需要给每个点染上\([1,k]\)中的某个颜色,图上有\(m\)条边,每条边\((u,v)\)有两种边权\(w_1\)(当\(u,v\)颜色相同时)和\(w_2\)......
  • 【XSY3270】Domino Colorings(轮廓线dp,状压)
    若已经知道了每个格子的颜色,我们可以用轮廓线DP(类似插头DP)判断棋盘是否能被多米诺骨牌填满,设\(dp[S]\)表示是否存在某种填法使得轮廓线每个位置是否被填的状态为\(S\)......
  • 【XSY2444】【BZOJ4042】【CERC2014】【luogu4757】Parades(树形dp+状压dp)
    题面Description从前有个A国,它有\(n\)个城市和\(n-1\)条道路。每条路连接两个城市。城市之间两两可达。每个城市与不超过10条道路相连。现在给出\(m\)条路径,要求从这些......
  • ventoy启动盘工具
    Ventoy简介简单来说,Ventoy是一个制作可启动U盘的开源工具。有了Ventoy你就无需反复地格式化U盘,你只需要把ISO/WIM/IMG/VHD(x)/EFI等类型的文件直接拷贝到U盘里面就可......
  • Ventoy制作的U盘启动盘无法进入esp分区,惠普笔记本电脑
    问题描述:开机F9进入启动项管理界面,选择Ventoy制作好的U盘启动盘提示未受信任的EFI,点击Enter返回启动项管理界面原因:惠普笔记本电脑的bios设置里的启动项设置中的安全启动......
  • AGC017F Zigzag【状压 DP】
    传送门以下认为\(n,m\)同阶。首先,我们可以根据每次走的方向用一个二进制数来表示一条折线。这样显然有一个傻逼DP,设\(f_{i,S}\)表示已经确定了前\(i\)条折线,其中......
  • 状压dp
    状压dp[SCOI2005]互不侵犯题目描述在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个......
  • 【题解】CF11D A Simple Task(状压 DP)
    【题解】CF11DASimpleTask题目链接CF11DASimpleTask题意概述给定一张\(n\)个点\(m\)条边的无向图,无重边自环,点数不超过\(19\),求无向图中环的数量。思路分......
  • 【软件更新】系统激活、硬盘检测、XMind、IDM、万兴PDF、李跳跳、SpeedTest、Ventoy、
    今天照例给大家更新一下之前发过的软件到新版本。大家可以打开每个软件下的链接查看,或者在公众号后台回复相应的关键词获取百度网盘和蓝奏云的下载链接。Windows和Office激......