首页 > 其他分享 >CF1466H 做题记录

CF1466H 做题记录

时间:2024-04-10 17:12:46浏览次数:23  
标签:DAG return 记录 ll tot CF1466H maxn define

link

非常 adhoc 的题,但是值得一练的好题!

一眼下去,我们会发现这个条件真的太过于抽象,根本无法想象。

注意到题目给了我们一个关键信息:一个排列组 \(\{b_1,b_2,...,b_n\}\) 对应唯一的好的分配方案。

考虑建立图论模型:每个人的编号向最喜欢的物品编号连边,形成一棵内向基环树森林。

对于基环树森林中的一个环,我们发现一定对应的 \(a\) 中的这个环。如果这个环没有在 \(a\) 中出现,那么环上每个点调整成这个环后会更优。

所以我们可以从森林中删掉这个环,然后继续一直这样做下去,最终会形成若干个环,就是 \(a\)。

考虑删去一个环后,原来连边指向这个环上的点的所有点都会重新调整连边,即连向 \(b_i\) 中下一个没有被删掉的点。

因此对于 \(i\),设 \(a_i\) 在 \(b_i\) 中的出现位置为 \(p\),那么 \(b_{i,1...p-1}\) 都是先前被删去的点。

这样对 \(a\) 中的环的出现时间建立了先后顺序的关系,容易想到把环缩成点,我们最终可以得到一张 DAG。

我们不难发现,只要连出来的有向图是 DAG(即没有环),就一定合法。

一张 DAG 对应若干方案,我们考虑对每一种 DAG 计算他的贡献,问题变为 DAG 计数,以及计算一张 DAG 的贡献。

DAG 计数是经典的,容斥即可。

对于一张 DAG,我们考虑每个环的后继环(包括自己)的总点数 \(p\),枚举这个环的任意一点 \(i\) 的 \(a_i\) 在 \(b_i\) 中的位置 \(j\),得到方案数为 \(A_{n-p}^{j-1}\times (n-j)!\)。

这个东西结合 DAG 计数,是容易的。

但是 \(n\le 40\),我们不能直接状压。注意到我们只关心状压集合 \(S\) 中所有环的大小,把 \(S\) 中环的大小的可重集 \(S'\) 作为状压集合即可,事实证明状态数不大。

总结:

  • 抽象模型,需要转化,常见转图论模型。

  • 尝试从不同的角度出发,不要死磕

  • 不要畏难,世界上没有不可做的题,只是不愿意思考罢了。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define pir pair<ll,ll>
#define mkp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
const ll maxn=42, mod=1e9+7;
ll n,a[maxn],cnt[maxn],d[maxn],siz[maxn],r[maxn],fac[maxn],ifac[maxn],f[10010];
ll find(ll x) {return x==d[x]? x:d[x]=find(d[x]);}
ll to[maxn];
ll Encode(){
	ll S=0;
	for(ll i=1;i<=n;i++) S=S*(cnt[i]+1)+to[i];
	return S+1;
} ll tot=0;
ll power(ll a,ll b=mod-2){
	ll s=1;
	while(b){
		if(b&1) s=s*a%mod;
		a=a*a%mod; b>>=1;
	} return s;
}
void dfs2(ll x,ll &ret){
	if(x>n){
		ll S=Encode();
		if(S==tot) return;
		ll c=mod-1, prod=1, p=0;
		for(ll i=1;i<=n;i++) p+=r[i]*i,
		prod=prod*fac[r[i]]%mod*ifac[to[i]]%mod*ifac[r[i]-to[i]]%mod;
		for(ll i=1;i<=n;i++){
			if(to[i]==r[i]) continue;
			if((r[i]-to[i])&1) c=mod-c;
			ll sum=0;
			for(ll j=1;j<=n-p+1;j++)
				sum=(sum+fac[n-p]*ifac[n-p-(j-1)]%mod*fac[n-j])%mod;
			prod=prod*power(sum,(r[i]-to[i])*i)%mod;
		} prod=prod*f[S]%mod;
		ret=(ret+c*prod)%mod; return;
	}
	for(ll i=0;i<=r[x];i++)
		to[x]=i, dfs2(x+1,ret);
}
void dfs(ll i){
	if(i>n){ ++tot;
		if(tot==1){
			f[1]=1; return;
		}
		for(ll i=1;i<=n;i++) r[i]=to[i];
		dfs2(1,f[tot]);
		return;
	}
	for(ll j=0;j<=cnt[i];j++){
		to[i]=j; dfs(i+1);
	}
}
int main(){
	scanf("%lld",&n); fac[0]=1;
	for(ll i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
	ifac[n]=power(fac[n]);
	for(ll i=n;i;i--) ifac[i-1]=ifac[i]*i%mod;
	for(ll i=1;i<=n;i++) d[i]=i, siz[i]=1;
	for(ll i=1;i<=n;i++){
		scanf("%lld",a+i);
		if(find(i)!=find(a[i])){
			siz[find(a[i])]+=siz[find(i)];
			d[find(i)]=find(a[i]);
		}
	}
	for(ll i=1;i<=n;i++)
		if(d[i]==i) ++cnt[siz[i]];
	dfs(1);
	printf("%lld",f[tot]);
	return 0;
}

标签:DAG,return,记录,ll,tot,CF1466H,maxn,define
From: https://www.cnblogs.com/Sktn0089/p/18126441

相关文章

  • Linux清除记录的常见方式
    隐藏远程SSH登陆记录清除当前的history记录隐藏Vim的操作记录隐藏文件修改时间锁定文件清除系统日志痕迹1.隐藏远程SSH登陆记录隐身登录系统,不会被w、last等指令检测到。[email protected]/bin/bash-i-T表示不分配伪终端,/usr/bin/bash表示在登录后......
  • 采用自定义注解 和 AOP 完成日志记录
    1、声明一个自定义注解@Retention注解包含一个RetentionPolicy类型的属性value,用于指定注解的保留策略,常用的保留策略包括:RetentionPolicy.SOURCE:表示注解仅在源代码中保留,编译器编译时会将其忽略,不会保存在编译后的字节码中。RetentionPolicy.CLASS:表示注解在编译后的......
  • 关于需要root权限启动图形应用记录
    关于需要root权限启动图形应用记录环境Kernel:6.8.4-arch1-1OS:ArchLinuxx86_64DE:hyprland问题来源在vmware中安装win11,想更改Edit>Preferences>Memory到"FitallvirtualmachinememoryintoreservedhostRAM"来提高访问内存效率,但必须用root运行vmware才能改变......
  • 什么是 DNS 记录?
    DNS记录是存储在DNS服务器上的文本指令。它们表明与一个域名相关的IP地址,也可以提供其他信息。DNS记录是计算机用语,指域名系统(DomainNameSystem,简称DNS)中的一条记录,这条记录存储于DNS服务器中。每一项记录包括了主机名、TTL值、类、类型、数据这几个字段。在Windows系统中,通过ns......
  • gob踩坑记录
    1.报错gob:duplicatetypereceived场景:使用encoder1发送自定义结构体struct1,encoder2发送自定义结构体struct2,使用同一个decoder接收这两个结构体。报错原因:gob在发送自定义结构体时,会先对该类型进行注册。在我们的场景中,encoder1和encoder2都向decoder发送注册信息,因......
  • 一些记录
    this关键字当前实例的引用:this关键字用于指代当前对象的实例。区分成员变量和局部变量:当成员变量与局部变量重名时,可以使用this来区分成员变量。例如,在构造器或方法中,this.variable指的是当前实例的成员变量variable,而简单的variable指的是局部变量。在构造器中调用其......
  • 蓝桥杯真题代码记录(最优清零方案
    目录1.题目:2.我的代码:小结:1.题目:给定一个长度为N的数列41,42,…,AN。现在小蓝想通过若干次操作将这个数列中每个数字清零。每次操作小蓝可以选择以下两种之一:1.选择一个大于0的整数,将它减去1;2.选择连续区个大于0的整数,将它们各减去1。小蓝最少经......
  • npm(Node Package Manager) 学习记录
    一、npm是什么npm是Node.js包管理器。是一个命令行工具,用于安装和管理Node.js项目中的代码库和工具。npm允许从npm注册表(一个大型的软件包数据库)中搜索、安装、更新和删除软件包,并处理这些软件包的依赖关系。npm已经成为Node.js生态系统中不可或缺的一部分,通......
  • CF&At记录1
    CF1916第一次熬夜打CF,感觉还行,可能是晚上人比较平静,思路就比较清晰。A本来是没什么要说的,但是傻了没开longlong,喜提FST!B题最开始想复杂了,开始慌了,但是静下来想想就发现只有两种情况,分类讨论一下就出来了。D题什么人类智慧题,幸好样例的给了提示,不然真不一定出的来。这......
  • 月或季持续更新中!!!记录过敏性鼻炎治疗踩过的坑!
      目前实测无效的有:西药区药名     靠谱程度(0-100)辅舒良    50(前期有效果,感冒的时候别用浪费钱,前期神中神,后期丐中丐。评价:不如空气)生理盐水   20(知乎百度专家以及抖音强推,衍生出各种流派,但我真想给0分,我的文章我做主)各种凝胶   -999999分(智......