当前位置: 首页 > news >正文

题解:CF1210F2 Marek and Matching (hard version)

详细揭秘如何 \(O(n \cdot 8^n \cdot 2^{2^ n})\)\(n=7\)


首先考虑假设已知图的形态,怎么判断是否存在完美匹配。

忘掉你学过的 hall 定理,考虑状压。设 \(f_{i, S}\) 表示左部点前 \(i\) 个和右部点集合 \(S\) 是否存在完美匹配。

那么考虑从 \(f_{i-1,S}\) 转移到 \(f_{i,*}\)。不难发现我们进行的操作其实就是,在左边添加点 \(i\),并在右边添加和 \(i\) 匹配的点。

枚举 \(i\) 的一个邻居 \(j\) 满足 \(j\) 还没被匹配过,即 \(j \not \isin S\),然后把 \(j\) 加入匹配点的集合。所以

\[f_{i, S \cup \{j\}} \leftarrow f_{i-1,S} \]

这是容易的。

然后,我们进行 dp of dp。我们直接把 \(f_{i, S}\) 的一行压成一个 \(2^{2^n}\) 状态。我们假设 \(g_{i, T}\) 表示考虑左部前 \(i\) 个点,\(f\) 的状态为 \(T\) 的概率。

转移的时候,我们先枚举和 \(i\) 相连的边集 \(E\),然后求出恰好这些边存在的概率,即 \(\prod \limits _{(i, j) \isin E} p_{i,j} \prod \limits _ {(i, j) \not \isin E}(1 - p_{i, j})\)

然后我们再枚举一个右部点的子集,将其作为前 \(i-1\) 个点的匹配集合。

最后我们枚举 \(i\) 的一个出边(要求这个边要在我们先前选的边集中),将这条边的终点作为 \(i\) 的匹配,更新 \(T\)

那么这道题就做完了。因为要枚举两个集合,以及枚举有效状态 \(T\),再加上我偷懒用 map 存状态所以会多乘一个 \(\log 2^{2^n}\),因此复杂度 \(O(n \cdot 8 ^ n\cdot 2^{2^n})\)


这玩意凭啥能过?

  • 关注到对于一个 \(i\)\(T\) 中的状态一定都是 \(\operatorname{popcount} = i\) 的。所以实际上有用的状态数量是 \(n \choose i\),峰值是 \({7 \choose 3} = 35\),比 \(2^n\) 小了不少。
  • 事实上我们只从有用的状态转移。打印出 \(n=7,i=4\) 时的有效状态数只有 \(30262\) 种。这下看着对多了!
#include<bits/stdc++.h>
#define endl '\n'
#define N 10
#define MOD 1000000007
using namespace std;
constexpr __uint128_t _1=1;
inline void mul(int &x,int y) {x=1ll*x*y%MOD;}
inline void add(int &x,int y) {x+=y,x-=x>=MOD?MOD:0;}
int n,p[N][N];
map<__uint128_t,int> mp[N];
void solve(int i)
{if(!i)return mp[i][1]=1,(void)0;for(auto [mask,val]:mp[i-1])for(int S=0;S<(1<<n);S++){int m=1; __uint128_t nxt=0;for(int j=0;j<n;j++)mul(m,(S>>j)&1?p[i][j+1]:(MOD+1-p[i][j+1]));for(int T=0;T<(1<<n);T++)for(int j=0;j<n;j++)if((mask>>T&1)&&!(T>>j&1)&&(S>>j&1))nxt|=_1<<(T|(1<<j));if(nxt&&val&&m)add(mp[i][nxt],1ll*val*m%MOD);}cerr<<mp[i].size()<<endl;
}
main()
{scanf("%d",&n);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&p[i][j]);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)p[i][j]=570000004ll*p[i][j]%MOD;for(int i=0;i<=n;i++)solve(i);printf("%d\n",mp[n][_1<<((1<<n)-1)]);return 0;
}
http://www.jsqmd.com/news/405815/

相关文章:

  • CF1322B
  • 2026年3月百度推广竞价广告开户代运营公司/服务商深度评测:深圳昊客网络 引领榜单 - 深圳昊客网络
  • 根脉与花开:AI元人文——中华文化思想在智能时代的原创性理论发展
  • AI Agent 框架探秘:拆解 OpenHands(7)--- Agent
  • 视频孪生之上:镜像视界矩阵视频融合驱动三维智慧交通升级——以重庆万州复杂立体交通场景为样本的统一空间坐标体系与跨摄像连续表达工程实践
  • 视频孪生之上 · 空间主权构建:镜像视界矩阵视频融合打造三维连续表达控制体系——基于统一坐标矩阵与动态修正机制的空间级主动感知与连续表达平台
  • 状压dp临行枚举类问题
  • 新的开始
  • CF1313D
  • 【Linux】进程地址空间的内核空间
  • [特殊字符] 基于YOLOv5/v8/v10的商超货架商品陈列面占比分析系统【完整源码+数据集】
  • JAVA WEB学习6
  • 【YOLO目标检测】基于YOLOv5/v8/v10的交通拥堵检测系统:从数据集构建到可视化界面全解析
  • 基于深度学习的鸡数量统计系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
  • 算法题避坑指南:数组/循环范围的 `+1` 到底什么时候加?
  • Neo4j学习笔记1
  • upload
  • 2026年生产力革命:实测上百款AI工具后,这5款真正重塑了我的工作流
  • 别再手动重复工作了!Skills技术让AI自动执行你的任务,收藏这篇就够了
  • AI记忆革命!MemOS开源框架实战:基于Graph的记忆图谱如何赋能LangChain智能体
  • 状压DP之棋盘放置类
  • 收藏级干货:10种AI产品形态全解析,2026年AI产品经理必备指南
  • JAVA WEB学习5
  • AI Agent开发者必看!三大推理框架深度解析与落地选型指南(收藏版)
  • 揭秘AI Agent:一个循环搞定所有任务,技术人必备,建议收藏反复阅读
  • 【必看收藏】企业AI Agent频频失败?90%的人都忽略了这一关键“语义层“构建技巧
  • 【GitHub项目推荐--Planning with Files:基于Manus AI工作流的智能任务管理革命】⭐⭐⭐⭐⭐
  • 微服务架构:Python 开发者的实践指南
  • 简单,但不显然
  • 在AI时代如何高效学习