题面传送门

一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% 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)的更多相关文章

  1. 【UOJ#75】【UR #6】智商锁(矩阵树定理,随机)

    [UOJ#75][UR #6]智商锁(矩阵树定理,随机) 题面 UOJ 题解 这种题我哪里做得来啊[惊恐],,, 题解做法:随机\(1000\)个点数为\(12\)的无向图,矩阵树定理算出它的生成树个 ...

  2. 矩阵树定理&BEST定理学习笔记

    终于学到这个了,本来准备省选前学来着的? 前置知识:矩阵行列式 矩阵树定理 矩阵树定理说的大概就是这样一件事:对于一张无向图 \(G\),我们记 \(D\) 为其度数矩阵,满足 \(D_{i,i}=\ ...

  3. [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)

    In some countries building highways takes a lot of time... Maybe that's because there are many possi ...

  4. BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]

    传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...

  5. bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 559  Solved: 325[Submit][Sta ...

  6. 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)

    [LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ...

  7. 2019.01.02 bzoj2467: [中山市选2010]生成树(矩阵树定理)

    传送门 矩阵树定理模板题. 题意简述:自己看题面吧太简单懒得写了 直接构建出这4n4n4n个点然后按照题面连边之后跑矩阵树即可. 代码: #include<bits/stdc++.h> # ...

  8. [CF917D]Stranger Trees[矩阵树定理+解线性方程组]

    题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...

  9. 【bzoj4596】[Shoi2016]黑暗前的幻想乡 容斥原理+矩阵树定理

    题目描述 给出 $n$ 个点和 $n-1$ 种颜色,每种颜色有若干条边.求这张图多少棵每种颜色的边都出现过的生成树,答案对 $10^9+7$ 取模. 输入 第一行包含一个正整数 N(N<=17) ...

随机推荐

  1. 【UE4 设计模式】建造者模式 Builder Pattern

    概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...

  2. django 中的hello word 开心,通过申请博客了,,发个随笔庆祝一下~~~~~~~

    django 中的hello word! 准备:[pymsql,pycharm,django3.0.7] >>>终端中:django-admin.py startproject [项 ...

  3. [no code][scrum meeting] Alpha 8

    项目 内容 会议时间 2020-04-14 会议主题 API文档第一版交付 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ). ...

  4. BUAA 2020 软件工程 软件分析案例作业

    Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业-软件分析案例 我在这个课程的目标是 学习软件 ...

  5. [BZOI2014]大融合——————线段树进阶

    竟然改了不到一小时就改出来了, 可喜可贺 Description Solution 一开始想的是边两侧简单路径之和的乘积,之后发现这是个树形结构,简单路径数就是节点数. 之后的难点就变成了如何求线段树 ...

  6. HCNP Routing&Switching之BGP路由属性和优选规则

    前文我们了解了BGP防环机制和路由聚合相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15458110.html:今天我们来聊一聊BGP路由属性和选路规 ...

  7. Springboot第一次访问慢,自身缺陷问题?

    一.现象: 1.访问controller,第一次速度在300-400ms,第二次访问就很快了大概在20ms,相差几十倍,是哪里出了问题,尝试了网上很多教程都没有作用 如启动参数设置 -Djava.se ...

  8. gcc中预定义的宏__GNUC__

    转载:gcc中预定义的宏__GNUC__ - Cccarl - 博客园 (cnblogs.com) 今天在看Linux系统编程这本书的代码的时候看到了__GNUC__,不太清楚这个宏所以去查了一下,以 ...

  9. copy-list-with-random-pointer leetcode C++

    A linked list is given such that each node contains an additional random pointer which could point t ...

  10. 深入剖析Redis客户端Jedis的特性和原理

    一.开篇 Redis作为目前通用的缓存选型,因其高性能而倍受欢迎.Redis的2.x版本仅支持单机模式,从3.0版本开始引入集群模式. Redis的Java生态的客户端当中包含Jedis.Rediss ...