Luogu4547 [THUWC2017]随机二分图
Description
Solution
题目本质上要求的是 种完备匹配乘上各自出现的概率乘上 之和
状态定义为 为左部点的集合为 ,右部点的集合为 的权值和
转移考虑枚举一条边
固定枚举边的顺序可以进行转移,考虑到 和数据范围,考虑记忆化搜索更为可行
同时还要注意的是要从按照二进制位从小到大进行转移,比较
最后来的瓶颈就是 了
第一种边是比较好做的,直接是
第二种边第三种边就不太好做
发现这里的式子只支持第一种边这种类别的,那么就考虑用期望线性性来拆边
先把两个边都用 插入
然后考虑差异
第二类边需要再插入两边并集 ,第三类边需要再插入两边并集且
(后面的就是考虑共同出现的情况)
Code
#include<bits/stdc++.h>
using namespace std;
#define reg register
#define For(i,a,b) for(reg int i=a;i<=b;++i)
#define Down(i,a,b) for(reg int i=b;i>=a;--i)
namespace yspm{
inline int read(){
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
inline int p(int x){return (1<<(x-1));}
const int N=1e5+10,mod=1e9+7;
struct edge{
int st,ed;
long long val;
}e[N];
#define ll long long
map<int,ll> f[N];
int inv2=5e8+4,inv4=25e7+2,cnt,n,m;
inline ll calc(int S,int T){
if(!S) return 1;
if(f[S].count(T)) return f[S][T];
For(i,1,cnt){
ll s=e[i].st,t=e[i].ed,v=e[i].val;
if((S|s)!=S||(T|t)!=T||S>=(s<<1)) continue;
f[S][T]=(f[S][T]+calc(S^s,T^t)*v%mod)%mod;
}
return f[S][T];
}
signed main(){
n=read(); m=read();
For(i,1,m){
int opt=read();
if(opt){
int x1=read(),x2=read(),x3=read(),x4=read();
e[++cnt]=(edge){p(x1),p(x2),inv2};
e[++cnt]=(edge){p(x3),p(x4),inv2};
if(x1==x3||x2==x4) continue;
if(opt==1) e[++cnt]=(edge){p(x1)|p(x3),p(x2)|p(x4),inv4};
else e[++cnt]=(edge){p(x1)|p(x3),p(x2)|p(x4),mod-inv4};
}
else{
e[++cnt].st=p(read());
e[cnt].ed=p(read());
e[cnt].val=inv2;
}
}
printf("%lld\n",(1<<n)*calc((1<<n)-1,(1<<n)-1)%mod);
return 0;
}
}signed main(){return yspm::main();}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律