UOJ 75 - 【UR #6】智商锁(矩阵树定理+随机+meet-in-the-middle)
一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% vfk yyds
u1s1 这种题目我是根本想不出来/kk,大概也就 jgh 这样的随机化带师才能想到出来吧
首先看到生成树计数可以很显然地想到矩阵树定理,但是由于此题是根据生成树个数构造合法的解的方案,所以一看就没有什么正经的做法(有提答题内味儿了)。
一个很显然的性质是:对于一张图我们可以考虑将其进行边双连通分量缩点,那么最终的生成树个数显然等于所有边双连通分量中生成树的乘积。这就启发我们采用这样一个思想,将原来 \(100\) 个点的图拆成若干个部分,对每个部分进行随机化,然后再像串糖葫芦一样将这些部分串起来。
然后就是我所想不到的地方了,考虑随机生成 \(1000\) 张由 \(15\) 个顶点(原题解是 \(12\) 个点,不过我认为都差不多罢)组成的图,每条边都有 \(70\%\) 的概率出现,并用矩阵树定理计算其中生成树的数量,我们记 \(f_i\) 表示第 \(i\) 张图的生成树个数 \(\bmod 998244353\),那么我们考虑求出一个四元组 \((a,b,c,d)\) 满足 \(f_af_bf_cf_d\equiv k\pmod{998244353}\),那么我们把 \(a,b,c,d\) 四张图串成一条链,形成一个 \(60\) 个点的图即可。那么怎么找出符合要求的 \((a,b,c,d)\) 呢?考虑用 meet-in-the-middle 的思想,枚举二元组 \(a,b\) 并将 \(f_af_b\) 的值放入一个 hashtable,然后枚举 hashtable 中的元素 \(v\) 并查看 \(k·v^{-1}\) 是否在 hashtable 中,这样即可在 \(\mathcal O(10^6)\) 的时间内求出符合要求的 \((a,b,c,d)\)。
最后我们要说明的问题是为什么这样做是正确的,或者说,为什么这个做法获得正确答案的概率很大。首先我们知道 \(15\) 个点的完全图中有 \(15^{13}\) 个生成树,该值是远远大于 \(998244353\) 的,也就是说这样的图的生成树个数在模上 \(998244353\) 中可以近似地看作均匀分布的,也就是说我们等价于随机生成了 \(1000\) 个 \(<998244353\) 的数,而这 \(1000\) 个数两两配对共可以得到 \(\dbinom{1000}{4}\approx 10^{11}\) 个不同的数,也就是说本题能够获得正确答案的概率等价于 \(10^{11}\) 个 \(<998244353\) 的数中包含全部 \(0\sim 998244352\) 的数的概率,简单想想就知道这个概率是很大的,如果真的要定量计算的话,那么每个数被覆盖的概率就是 \(1-(1-\dfrac{1}{998244353})^{10^{11}}\approx 1-e^{-100}\),该值大约是 \(1-10^{-44}\),这样一来所有数都被覆盖的概率大约就是 \((1-10^{-44})^{998244353}\),我用计算器摁了一下,\((1-10^{-28})^{10^9}\) 大约是 \(0.99997\),而前者显然比后者更大,因此正确性是可以保证的。
最后注意特判 \(k=0\),因为生成树个数为 \(998244353\) 的倍数的概率显然远远小于不是 \(998244353\) 的倍数。
const int MOD=998244353;
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
struct graph{
bool has[17][17];
int a[17][17],cnt;
void add(int x,int y){
x--;y--;
a[x][y]=(a[x][y]-1+MOD)%MOD;
a[y][x]=(a[y][x]-1+MOD)%MOD;
a[x][x]=(a[x][x]+1)%MOD;
a[y][y]=(a[y][y]+1)%MOD;
}
int getdet(){
int sgn=1;
for(int i=1;i<15;i++){
int t=i;
for(int j=i+1;j<15;j++) if(a[j][i]) t=j;
if(t!=i) sgn=-sgn;
for(int j=i;j<15;j++) swap(a[i][j],a[t][j]);
int iv=qpow(a[i][i],MOD-2);
for(int j=i+1;j<15;j++){
int mul=1ll*(MOD-a[j][i])*iv%MOD;
for(int k=i;k<15;k++) a[j][k]=(a[j][k]+1ll*mul*a[i][k])%MOD;
}
} int res=(sgn+MOD)%MOD;
for(int i=1;i<15;i++) res=1ll*res*a[i][i]%MOD;
return res;
}
void gen(){
for(int i=1;i<=15;i++) for(int j=1;j<i;j++){
int pro=rand()%10;
if(pro>2) has[i][j]=has[j][i]=1,add(i,j);
} cnt=getdet();
}
} g[1005];
map<int,pii> mul;
int main(){
srand(20060729);
for(int i=1;i<=1000;i++) g[i].gen();
for(int i=1;i<=1000;i++) for(int j=1;j<=i;j++)
mul[1ll*g[i].cnt*g[j].cnt%MOD]=mp(i,j);
int qu;scanf("%d",&qu);
while(qu--){
int t;scanf("%d",&t);
if(!t){printf("%d %d\n%d %d\n",3,1,1,2);continue;}
for(map<int,pii>::iterator it=mul.begin();it!=mul.end();it++){
int val=it->fi,rst=1ll*t*qpow(val,MOD-2)%MOD;
if(mul.count(rst)){
vector<pii> ans;
int a=it->se.fi,b=it->se.se,c=mul[rst].fi,d=mul[rst].se;
// printf("%d %d %d %d\n",a,b,c,d);
// printf("%d %d %d %d\n",g[a].cnt,g[b].cnt,g[c].cnt,g[d].cnt);
for(int i=1;i<=15;i++) for(int j=1;j<i;j++) if(g[a].has[i][j]) ans.pb(mp(i,j));
for(int i=1;i<=15;i++) for(int j=1;j<i;j++) if(g[b].has[i][j]) ans.pb(mp(15+i,15+j));
for(int i=1;i<=15;i++) for(int j=1;j<i;j++) if(g[c].has[i][j]) ans.pb(mp(30+i,30+j));
for(int i=1;i<=15;i++) for(int j=1;j<i;j++) if(g[d].has[i][j]) ans.pb(mp(45+i,45+j));
ans.pb(mp(1,16));ans.pb(mp(16,31));ans.pb(mp(31,46));
printf("%d %d\n",60,ans.size());
for(pii e:ans) printf("%d %d\n",e.fi,e.se);
break;
}
}
}
return 0;
}
UOJ 75 - 【UR #6】智商锁(矩阵树定理+随机+meet-in-the-middle)的更多相关文章
- 【UOJ#75】【UR #6】智商锁(矩阵树定理,随机)
[UOJ#75][UR #6]智商锁(矩阵树定理,随机) 题面 UOJ 题解 这种题我哪里做得来啊[惊恐],,, 题解做法:随机\(1000\)个点数为\(12\)的无向图,矩阵树定理算出它的生成树个 ...
- 矩阵树定理&BEST定理学习笔记
终于学到这个了,本来准备省选前学来着的? 前置知识:矩阵行列式 矩阵树定理 矩阵树定理说的大概就是这样一件事:对于一张无向图 \(G\),我们记 \(D\) 为其度数矩阵,满足 \(D_{i,i}=\ ...
- [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)
In some countries building highways takes a lot of time... Maybe that's because there are many possi ...
- BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]
传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...
- bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 559 Solved: 325[Submit][Sta ...
- 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
[LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...
- 2019.01.02 bzoj2467: [中山市选2010]生成树(矩阵树定理)
传送门 矩阵树定理模板题. 题意简述:自己看题面吧太简单懒得写了 直接构建出这4n4n4n个点然后按照题面连边之后跑矩阵树即可. 代码: #include<bits/stdc++.h> # ...
- [CF917D]Stranger Trees[矩阵树定理+解线性方程组]
题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...
- 【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理
题目描述 给出 $n$ 个点和 $n-1$ 种颜色,每种颜色有若干条边.求这张图多少棵每种颜色的边都出现过的生成树,答案对 $10^9+7$ 取模. 输入 第一行包含一个正整数 N(N<=17) ...
随机推荐
- 如何查找一个目录中所有c文件的总行数
如何查找一个目录中所有c文件的行数 面试题问到了一题,如何统计wc文件夹下所有文件的行数,包括了子目录. 最后在 https://blog.csdn.net/a_ran/article/details ...
- EMC测试国家标准GB/T 17626
转载: 详解EMC测试国家标准GB/T 17626 - whik - 博客园 (cnblogs.com)
- JavaScript05
显示和隐藏 元素的显示和隐藏 元素display属性可控制元素的显示和隐藏,先获取元素对象,再通过点语法调用style对象中的display属性 语法格式: 元素.style.display='non ...
- 【UE4 C++ 基础知识】<3> 基本数据类型、字符串处理及转换
基本数据类型 TCHAR TCHAR就是UE4通过对char和wchar_t的封装 char ANSI编码 wchar_t 宽字符的Unicode编码 使用 TEXT() 宏包裹作为字面值 TCHAR ...
- [no code][scrum meeting] Alpha 14
项目 内容 会议时间 2020-04-22 会议主题 周中讨论会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalog() ...
- netty传输java bean对象
在上一篇博客(netty入门实现简单的echo程序)中,我们知道了如何使用netty发送一个简单的消息,但是这远远是不够的.在这篇博客中,我们来使用netty发送一个java bean对象的消息,但是 ...
- HZOI帝国2019欢乐时刻
前言: update 只是恢复一下原来手残删掉的博客,不是在水,嘤嘤嘤 update 以后改成Stack,但是之前的就懒得改了... by 10.31 为了窝的访问量大家的好心情,模仿学长搞了一个这个 ...
- Linux多线程编程之详细分析
线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我见到这样一道面试题: 是否熟悉POSIX多线程 ...
- MySQL 的架构与组件
MySQL 的逻辑架构图设计图 连接/线程处理:管理客户端连接/会话[mysql threads] 解析器:通过检查SQL查询中的每个字符来检查SQL语法,并为每个SQL查询生成 SQL_ID. 此 ...
- 『学了就忘』Linux基础 — 15、了解Linux系统的目录结构
目录 1.一级目录说明 (1)一级目录列表 (2)/bin/和/sbin/目录说明 (3)/boot/目录说明 (4)/lib/和/lib64/目录说明 (5)/lost+found/目录说明 (6) ...