UOJ#75. 【UR #6】智商锁 随机化算法 矩阵树定理
原文链接www.cnblogs.com/zhouzhendong/p/UOJ75.html
前言
根本没想到。
题解
首先我们可以考虑一种做法:
找一些图,使得他们各自的生成树个数乘起来等于 k。
那么只要将他们用一条链连起来就得到答案了。
接下来考虑如何得到这些图。
考虑随机生成一个 n 个点的图,它的生成树个数最大是 $n^{n-2}$ 。
我们假装一个 n 个点的图的生成树个数是 $[0,n^{n-2}]$ 中的随机数。
假设我们随机生成了 S 个这样的图,如果我们在这 S 个图中随机选择 t 个连起来,那么我们就得到了 $S^t$ 个随机数。
令 n = 12, S = 1000, t = 4,由于 $n^{n-2} = 12^{10}> 62\cdot 998244353$,所以我们可以在对 998244353 取模之后把生成树个数当作一个 $[0,998244353)$ 中的随机数。则我们得到了 $S^t = 10^{12}$ 个随机数。这 $10^{12}$ 个数中不含有 k 个概率非常小。
我们不可能把所有所有的这些随机数都求出来,所以我们用类似于 BSGS 的办法折半一下就好了。
代码
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=1005,M=20,mod=998244353;
void Add(int &x,int y){
if ((x+=y)>=mod)
x-=mod;
}
void Del(int &x,int y){
if ((x-=y)<0)
x+=mod;
}
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod)
if (y&1)
ans=(LL)ans*x%mod;
return ans;
}
vector <pair <int,int> > g[N];
int val[N],ival[N];
int calc(int n,vector <pair <int,int> > &e){
static int a[M][M];
clr(a);
for (auto E : e){
int x=E.fi,y=E.se;
a[x][y]++,a[y][x]++;
a[x][x]--,a[y][y]--;
}
For(i,1,n)
For(j,1,n)
if (a[i][j]<0)
a[i][j]+=mod;
n--;
For(i,1,n){
For(j,i,n)
if (a[j][i]!=0){
For(k,i,n)
swap(a[i][k],a[j][k]);
break;
}
if (a[i][i]==0)
return 0;
For(j,i+1,n){
int v=(LL)a[j][i]*Pow(a[i][i],mod-2)%mod;
For(k,i,n)
Del(a[j][k],(LL)a[i][k]*v%mod);
}
}
int ans=mod-1;
For(i,1,n)
ans=(LL)ans*a[i][i]%mod;
return ans;
}
struct hash_map{
static const int Ti=233,mod=1<<20;
int cnt,k[mod+1],v[mod+1],nxt[mod+1],fst[mod+1];
int Hash(int x){
int v=x&(mod-1);
return v==0?mod:v;
}
void clear(){
cnt=0;
memset(fst,0,sizeof fst);
}
void update(int x,int a){
int y=Hash(x);
for (int p=fst[y];p;p=nxt[p])
if (k[p]==x){
v[p]=a;
return;
}
k[++cnt]=x,nxt[cnt]=fst[y],fst[y]=cnt,v[cnt]=a;
return;
}
int find(int x){
int y=Hash(x);
for (int p=fst[y];p;p=nxt[p])
if (k[p]==x)
return v[p];
return 0;
}
int &operator [] (int x){
int y=Hash(x);
for (int p=fst[y];p;p=nxt[p])
if (k[p]==x)
return v[p];
k[++cnt]=x,nxt[cnt]=fst[y],fst[y]=cnt;
return v[cnt]=0;
}
}Map;
int S=1000;
void prework(){
srand(_SEED_);
int n=12;
For(i,1,S){
For(j,1,n)
For(k,1,j-1)
if (rand()%10>=2)
g[i].pb(mp(j,k));
val[i]=calc(n,g[i]);
ival[i]=Pow(val[i],mod-2);
}
Map.clear();
For(i,1,S)
For(j,1,i){
int tmp=(LL)val[i]*val[j]%mod;
Map[tmp]=i*(S+1)+j;
}
}
void solve(int x){
if (!x)
return (void)puts("2 0");
For(i,1,S)
For(j,1,i){
int tmp=(LL)x*ival[i]%mod*ival[j]%mod;
if (Map[tmp]){
int v[4]={i,j,Map[tmp]/(S+1),Map[tmp]%(S+1)};
vector <pair <int,int> > res;
res.clear();
int n=48,cnt=0;
For (k,0,3){
if (cnt>0)
res.pb(mp(cnt,cnt+1));
for (auto e : g[v[k]])
res.pb(mp(e.fi+cnt,e.se+cnt));
cnt+=12;
}
printf("%d %d\n",n,(int)res.size());
for (auto e : res)
printf("%d %d\n",e.fi,e.se);
return;
}
}
}
int main(){
prework();
int T=read();
while (T--)
solve(read());
return 0;
}
UOJ#75. 【UR #6】智商锁 随机化算法 矩阵树定理的更多相关文章
- 【UOJ#75】【UR #6】智商锁(矩阵树定理,随机)
[UOJ#75][UR #6]智商锁(矩阵树定理,随机) 题面 UOJ 题解 这种题我哪里做得来啊[惊恐],,, 题解做法:随机\(1000\)个点数为\(12\)的无向图,矩阵树定理算出它的生成树个 ...
- UOJ 75 - 【UR #6】智商锁(矩阵树定理+随机+meet-in-the-middle)
题面传送门 一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% vfk yyds u1s1 这种题目我是根本想不出来/kk,大概也就 jgh 这样的随机化带师才能想到出来吧 首先看到生成树 ...
- 【构造 meet in middle 随机 矩阵树定理】#75. 【UR #6】智商锁
没智商了 变式可见:[构造 思维题]7.12道路建设 当你自信满满地把你认为的正确密码输入后,时光机滴滴报警 —— 密码错误.你摊坐在了地上. 黑衣人满意地拍了拍你的肩膀:“小伙子,不错嘛.虽然没解开 ...
- UOJ#121. 【NOI2013】向量内积 随机化算法,矩阵
原文链接www.cnblogs.com/zhouzhendong/UOJ121.html 前言 完蛋了我越来越菜了贺题都不会了. 题解 $O(n ^ 2 d) $ 暴力送 60 分. Bitset 优 ...
- 【算法】Matrix - Tree 矩阵树定理 & 题目总结
最近集中学习了一下矩阵树定理,自己其实还是没有太明白原理(证明)类的东西,但想在这里总结一下应用中的一些细节,矩阵树定理的一些引申等等. 首先,矩阵树定理用于求解一个图上的生成树个数.实现方式是:\( ...
- 算法复习——矩阵树定理(spoj104)
题目: In some countries building highways takes a lot of time... Maybe that's because there are many p ...
- POJ 矩阵相乘 (随机化算法-舍伍德(Sherwood))
周三的算法课,主要讲了随机化算法,介绍了拉斯维加斯算法,简单的理解了为什么要用随机化算法,随机化算法有什么好处. 在处理8皇后问题的时候,穷举法是最费时的,回朔比穷举好点,而当数据量比较大的时候,如1 ...
- POJ3318--Matrix Multiplication 随机化算法
Description You are given three n × n matrices A, B and C. Does the equation A × B = C hold true? In ...
- 2018.09.14 codeforces364D(随机化算法)
传送门 根据国家集训队2014论文集中胡泽聪的随机化算法可以通过这道题. 对于每个数,它有12" role="presentation" style="posi ...
随机推荐
- 20175221 MyCP(课下作业,必做)
MyCP(课下作业,必做) 任务详情 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: - java MyCP -tx XXX1.txt XXX2 ...
- easyUI文本框获得焦点,失去焦点
easyUI帮助文档对于文本框的操作没有提供直接获得焦点,或者失去焦点的方法,我们可以采用以下写法来实现. 获得焦点: $('input',$('#文本框Id').next('span')).focu ...
- 如何为 Jupyter Notebook 安装代码提示功能
按照上一篇博客安装完 Python 和 Jupyter Notebook 后,我们已经可以使用 Notebook 愉快的编写 Python 代码了,但是发现它不像其他编辑器那样会弹出代码提示,这稍微有 ...
- ArcGis使用字段别名Alias Name导出Excel
在ArcMap10.3+(根据官网描述应该是,作者测试使用10.5,可行)以后的版本,可以使用ArcToolbox工具导出Excel. 工具位置ConversionTools——Excel——Tabl ...
- python3 练手实例3 摄氏温度与华氏温度转换
def wd(): w=input('请输入一个摄氏温度或者一个华氏温度,如,34c/C or 34f/F:') if w[-1] in ['c','C']: w=float(w[:-1]) hs=1 ...
- java 根据经纬度坐标计算两点的距离算法
/** * @Desc 根据经纬度坐标计算两点的距离算法<br> * @Author yangzhenlong <br> * @Data 2018/5/9 18:38 */ p ...
- 2、搭建一个简单的Web项目
一.创建一个Web项目: 1.File->new Project->Java->JavaEE->Web Application 2.为项目起名: 3.配置项目:在项目上击右键- ...
- 浏览器将URL变成一个屏幕上显示的网页的过程?
前言 一个浏览器是怎么工作的? 正文 URL变网页过程: 1.浏览器通过http或https协议,向服务端请求页面 2.将请求过来的HEML代码通过解析,构建DOM树 3.计算DOM树上的CSS属性 ...
- 【前端】ACE Editor(代码编辑器) 简易使用示例
身为一个早已退役的Oier,当然忘不了当年一个个OJ页面上的代码显示和代码编辑器. 其中,洛谷使用的ACE Editor就是之一,非常的简洁美观.以及实际上在前端页面上搭建一个ACE Editor也是 ...
- 按Ctrl+Enter发送的实现
按Ctrl+Enter发送 1, 监听textarea的onkeydown事件 <textarea tabindex="1" class="ie6ta" ...