没智商了

变式可见:【构造 思维题】7.12道路建设

当你自信满满地把你认为的正确密码输入后,时光机滴滴报警 —— 密码错误。你摊坐在了地上。

黑衣人满意地拍了拍你的肩膀:“小伙子,不错嘛。虽然没解开密码,但是离解开密码也不远咯。其实刚才是个对你的考验。来加入我们保护星期日委员会吧!”

你惊讶得从地上直接 splay 了起来:“就是那个传说中的保护星期日委员会?咦,那为什么今天星期日还要上学呢?”

黑衣人:“你不是高三学生吗?”,你一脸无语。黑衣人又说道:“小伙子跟我干吧,我们一起去摧毁 IIIS。”

于是你们跋山涉水来到了 IIIS 基地的一个秘密仓库门前。duang地一下放倒了门卫之后你们试图开门窃取秘密资料。可是这个门装备了最新的智商锁,只有你的智商恰好等于锁的主人门才会打开。于是门上出现一道迷题:

给你一个 k,请你构造一个结点数不超过 100 的无向图,使得这个无向图中生成树的个数对 $998244353$(7×17×223+1,一个质数)取模后恰为 k。

作为智商超高的你一定一眼秒掉了此题!请写一个程序证明你的智商跟智商锁的主人一样吧!

输入格式

第一行一个正整数 T。

接下来 T 行每行一个非负整数 k,保证 $0≤k<998244353$。

输出格式

你需要对每一个给出来的 $k$,输出一张无自环无重边的无向图。如果有多解输出任意一组解均可。如果无解请输出卖萌表情 “QwQ”(不含引号)。

输出无向图时,先一行两个非负整数 $n,m$,分别表示结点数和边数。你需要满足 $1≤n≤100$。接下来 m 行,每行两个整数 v,u 表示 v 号结点和 u 号结点之间有一条无向边。结点从 1 到 n 编号。


题目分析

随机个1000张图,由于一张点数为$n$的完全图生成树个数为$g_i=n^{n-2}$,那么当$n\ge 10$左右时候$g_i$就可看作在模$p$意义下的一个均匀分布的随机数.

考虑如何由两张图得到一个更大的答案:因为两张图之间本没有边相连,那如果任连一条桥边,就意味着新图的生成树必定要包括这条桥.所以两张图$f,g$可以得到一张新图$h=f\times g$.

接下去就是乱搞用meet in middle找出四元组使得其乘积在模$p$下为$K$.

因为生成的图的生成树数量可视作均匀分布的随机数,所以选四个得到$K$的概率是很大的。

最后还是挂个吉利题解吧……

接下来我们来考虑一种合理的构造方法,直接构造是比较困难的,因为我们现在只能对答案进行乘法(见第七个点)而无法进行加法。于是我们就可以开始尝试乱搞。

标程的做法是:随机1000张点数为12的无向图,用基尔霍夫矩阵求出第$i$张图的生成树个数$f_i$。然后对于每一个$K$,我们试图找到一个四元组$(a,b,c,d)$使得$f_a×f_b×f_c×f_d\equiv K \pmod{998244353}$,这个显然是可以meet in middle的,我们预处理它们两两的乘积与乘积的逆元,借助hash表就可以在约$10^6$级别的运算量下找到一个合法的四元组。

这个做法相当于自行对最终的图添加了一个比较严苛的条件进行求解,为什么这样是靠谱的呢?接下来提供一种对正确性大致的解释(以下是数学渣JRY在没有任何道理的情况进行的口胡):

首先我们随机无向图的方法是每一条边生成的概率都是$0.8$,而12个点的完全图的生成树个数是$12^{10}$,这是远大于模数的,所以我们可以近似地把$fi$看做均匀分布的随机数(这个和我们平时写的哈希表的思想类似)。接下来我们把这$1000$个随机数的集合四次方再模上模数,这样我们就得到了$10^{12}$个数,和刚才同理,我们也可以把这$10^{12}$个数给近似地看成均匀分布的随机数。

接下来我们要求的是$10^{12}$个小于等于$10^9$的随机数完全覆盖0到$10^9$之间所有数的概率是多少。首先一个数被覆盖的概率是$1-(1-\frac{1}{10^9})^{10^{12}} \approx 1-\mathrm{e}^{-10^3}$,我们可以近似地认为所有数都被覆盖的概率是$(1-\mathrm{e}^{-10^3})^{10^9}$,实际上这个数是非常接近$1$的(因为$e^{10^3}$比$10^9$大到哪里去都不知道了)

话说我生成图的方式好像有点奇怪?

 #include<bits/stdc++.h>
#define MO 998244353
const int maxn = ;
const int maxm = ; int qmi(int a, int b)
{
int ret = ;
for (; b; b>>=,a=1ll*a*a%MO)
if (b&) ret = 1ll*ret*a%MO;
return ret;
}
std::set<int> gcnt;
struct Graph
{
int n,m,val;
int fa[maxn],f[maxn][maxn],deg[maxn];
bool mp[maxn][maxn]; Graph(){memset(mp, , sizeof mp);}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int Gauss(int n)
{
int ret = ;
for (int i=; i<=n; i++)
{
if (!f[i][i]) return ;
for (int j=i+; j<=n; j++)
if (f[j][i]){
int det = 1ll*f[j][i]*qmi(f[i][i], MO-)%MO;
for (int k=i; k<=n; k++)
f[j][k] = (f[j][k]-1ll*f[i][k]*det%MO+MO)%MO;
}
}
for (int i=; i<=n; i++)
ret = 1ll*ret*f[i][i]%MO;
return ret;
}
void output(int det)
{
for (int p=; p<=n; p++)
for (int t=p+; t<=n; t++)
if (mp[p][t]) printf("%d %d\n",p+det,t+det);
}
void random(int Range)
{
val = ;
do{
memset(f, , sizeof f);
memset(mp, , sizeof mp);
n = rand()%Range+, m = std::min(n-+rand()%(n*(n-)/-n+), n*(n-)/);
for (int i=; i<=n; i++) fa[i] = i;
for (int i=; i<n; i++)
{
int u = rand()%n+, v = rand()%n+;
while (find(u)==find(v))
u = rand()%n+, v = rand()%n+;
fa[fa[u]] = fa[v];
mp[u][v] = mp[v][u] = true;
f[u][v] = f[v][u] = MO-;
++f[u][u], ++f[v][v];
}
for (int i=n; i<=m; i++)
{
int u = rand()%n+, v = rand()%n+;
while (mp[u][v]||v==u)
u = rand()%n+, v = rand()%n+;
mp[u][v] = mp[v][u] = true;
f[u][v] = f[v][u] = MO-;
++f[u][u], ++f[v][v];
}
for (int i=; i<=n; i++)
for (int j=; j<=n; j++)
if (f[i][j] < ) f[i][j] += MO;
val = Gauss(n-);
}while (gcnt.count(val));
gcnt.insert(val);
}
}f[];
struct node
{
int idx,idy,val;
bool operator < (node a) const
{
return val < a.val;
}
}ddc[];
int T,n,tot;
bool legal; void init()
{
srand(time());
f[].n = f[].val = , gcnt.insert();
f[].n = f[].val = , gcnt.insert();
f[].n = f[].val = , gcnt.insert();
for (int i=; i<=; i++) f[i].random();
for (int i=; i<=; i++) f[i].random();
for (int i=; i<=; i++)
for (int j=i+; j<=; j++)
ddc[++tot].val = 1ll*f[i].val*f[j].val%MO,
ddc[tot].idx = i, ddc[tot].idy = j;
std::sort(ddc+, ddc+tot+);
}
void output(int id1, int id2, int id3, int id4)
{
int det = ;
int n1 = f[id1].n, n2 = f[id2].n, n3 = f[id3].n, n4 = f[id4].n;
if (n1+n2+n3+n4 > ) return;
printf("%d %d\n",n1+n2+n3+n4,f[id1].m+f[id2].m+f[id3].m+f[id4].m+);
f[id1].output(det), det += n1, printf("1 %d\n",det+);
f[id2].output(det), det += n2, printf("1 %d\n",det+);
f[id3].output(det), det += n3, printf("1 %d\n",det+);
f[id4].output(det), det += n4;
legal = true;
}
int main()
{
init();
for (scanf("%d",&T); T; --T)
{
scanf("%d",&n), legal = false;
if (n==){
puts("2 0");continue;
}
for (int i=; i<=&&!legal; i++)
for (int j=i+; j<=&&!legal; j++)
{
int trans = 1ll*n*qmi(1ll*f[i].val*f[j].val%MO, MO-)%MO;
int L = , R = tot, pos = -;
for (int mid=(L+R)>>; L<=R; mid=(L+R)>>)
if (ddc[mid].val <= trans) pos = mid, L = mid+;
else R = mid-;
if (ddc[pos].val==trans)
output(ddc[pos].idx, ddc[pos].idy, i, j);
}
if (!legal) puts("QwQ");
}
return ;
}

END

【构造 meet in middle 随机 矩阵树定理】#75. 【UR #6】智商锁的更多相关文章

  1. UOJ 75 - 【UR #6】智商锁(矩阵树定理+随机+meet-in-the-middle)

    题面传送门 一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% vfk yyds u1s1 这种题目我是根本想不出来/kk,大概也就 jgh 这样的随机化带师才能想到出来吧 首先看到生成树 ...

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

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

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

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

  4. CSU 1805 Three Capitals(矩阵树定理+Best定理)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1805 题意: A和B之间有a条边,A和G之间有b条边,B和G之间有c条边.现在从A点出发走遍所 ...

  5. 【Learning】矩阵树定理 Matrix-Tree

    矩阵树定理 Matrix Tree ​ 矩阵树定理主要用于图的生成树计数. 看到给出图求生成树的这类问题就大概要往这方面想了. 算法会根据图构造出一个特殊的基尔霍夫矩阵\(A\),接着根据矩阵树定理, ...

  6. CF917D. Stranger Trees & TopCoder13369. TreeDistance(变元矩阵树定理+高斯消元)

    题目链接 CF917D:https://codeforces.com/problemset/problem/917/D TopCoder13369:https://community.topcoder ...

  7. 算法复习——矩阵树定理(spoj104)

    题目: In some countries building highways takes a lot of time... Maybe that's because there are many p ...

  8. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

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

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

随机推荐

  1. 一次JDBC支持表情存储的配置过程

    公司的一个项目,一开始没有考虑到内容字段支持表情,有一个接入方的内容含有表情要支持下 项目是基于Springboot的. 方案1先尝试直接配置数据库连接 shardingsphere: datasou ...

  2. 快速排序的js实现

    该方法的基本思想是: 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边. 3.再对左右区间重复第二步,直到各区间只有一个数. var ...

  3. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

    MFC中ASSERT作为断言语句,括号内内容为TRUE,继续执行:为FALSE终止执行.之后取得当前窗口的系统菜单,在这个菜单中添加字符串资源IDS_ABOUTBOX和菜单资源IDM_ABOUTBOX ...

  4. drf-更新四大接口-单改整体-单改局部-群改整体-群改局部-04

    目录 复习 基于前一天序列化基础 整体单改 单与整体局部修改 复习 """ 1.ModelSerializer序列化类 models.py class BaseModel ...

  5. MGR复制

    CentOS7 配置如下 5.7.22 Group ReplicationMySQL5.7.22安装略   在三台db服务器上面设置/etc/hosts映射,如下:192.168.1.101 mydb ...

  6. T100——英文版凭证报表

    范例:cxrr001 效果:增加英文版报表选择 1.azzi301,复制cxrr001_g01,把样板编号改为cxrr001_g01_01: 2.下载cxrr001_g01的GR样板,把cxrr001 ...

  7. 02docker核心概念

    1:docker三大核心概念 核心概念 描述 镜像 Docker镜像类似于虚拟机镜像,可以将它理解为一个只读的模板. 容器 Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用 ...

  8. Java Web ActiveMQ与WebService的异同

    Webservice 和MQ(MessageQueue)都是解决跨平台通信的常用手段 一.WebService:用来远程调用服务,达到打通系统.服务复用的目的.是SOA系统架构——面向服务架构的体现. ...

  9. SharePoint Resize app

    //Global Variables used in different functions. var widthSelected=null; var senderId; var hostUrl = ...

  10. 使用EF Core 连接远程oracle 不需要安装oracle客户端方法

    连接字符串: Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=IP地址(PORT=1521))(CONNECT_DATA=(SERVICE_ ...