题面传送门

一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% 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. JavaScript04

    分离绑定事件 使用分离方式绑定元素事件可以使用页面元素与JavaScript代码完全分离,有利于代码分工和维护,是目前开发主流,分为两步: 1.获取需要绑定事件的元素 语法:根据id属性值取元素节点 ...

  2. 【数据结构与算法Python版学习笔记】算法分析

    什么是算法分析 算法是问题解决的通用的分步的指令的聚合 算法分析主要就是从计算资源的消耗的角度来评判和比较算法. 计算资源指标 存储空间或内存 执行时间 影响算法运行时间的其他因素 分为最好.最差和平 ...

  3. 软件工程个人博客作业-软件案例分析:VS与VS Code

    项目 内容 本作业属于北航 2020 年春软件工程 博客园班级连接 本作业是本课程个人项目作业 作业要求 我在这个课程的目标是 提高软件开发能力.团队协作能力 这个作业在哪个具体方面帮助我实现目标 提 ...

  4. 2021.8.12考试总结[NOIP模拟37]

    T1 数列 考场上切掉的简单题. $a$,$b$与数列中数的正负值对答案无关.全当作正数计算即可. $exgcd$解未知数系数为$a$,$b$,加和为$gcd(a,b)$的不定方程组,再枚举每个数.如 ...

  5. 用Python画如此漂亮的专业插图 ?简直So easy!

    本文整理自知乎问答,仅用于学术分享,著作权归作者所有.如有侵权,请联系我删文处理.多多转发,多多学习! 方法一 强烈推荐 Python 的绘图模块 matplotlib: python plottin ...

  6. 排序算法:Java实现希尔排序

    希尔排序的思路是先分组再整合 先对下标进行分组,比如当数组长度为20时,一开始选定一个间隔值为10 对数组进行排序,每隔10个元素比较大小并交换,以下标为间隔,1和11比较.2和12比较......1 ...

  7. hdu 4771 Stealing Harry Potter's Precious (BFS+状压)

    题意: n*m的迷宫,有一些格能走("."),有一些格不能走("#").起始点为"@". 有K个物体.(K<=4),每个物体都是放在& ...

  8. Beam Search快速理解及代码解析

    目录 Beam Search快速理解及代码解析(上) Beam Search 贪心搜索 Beam Search Beam Search代码解析 准备初始输入 序列扩展 准备输出 总结 Beam Sea ...

  9. git diff 比较差异

    说明 以下命令可以不指定 <filename>,表示对全部文件操作. 命令涉及和 Git本地仓库对比的,均可指定 commit 的版本. HEAD 最近一次 commit HEAD^ 上次 ...

  10. mysql批量修改某一列的值为另外的值

    sql语句 UPDATE tb_info SET org_id = 2170 WHERE org_id = 815