洛谷 P5406 - [THUPC2019]找树(FWT+矩阵树定理)
首先看到这道题你必须要有一个很清楚的认识:这题新定义的 \(\oplus\) 符号非常奇怪,也没有什么性质而言,因此无法通过解决最优化问题的思路来解决这个问题,只好按照计数题的思路来解决,即考虑 \(cnt_k\) 表示权值为 \(k\) 的生成树的个数,那么我们即求最大的满足 \(cnt_k\ne 0\) 的 \(k\)。
考虑怎样维护这个东西,首先考虑一个非常 trivial 的情况,如果题目中求生成树权值的方法不是这个奇怪的 \(\oplus\) 运算而是加法怎么办。那么对于一条权值为 \(w\) 的边,如果它在生成树中,它会对生成树权值产生 \(w\) 的贡献,因此很自然地想到用幂级数表示权值,即将每条边看作一个幂级数 \(x^w\),然后跑矩阵树定理会得出一个幂级数 \(F(x)\),那么权值为 \(v\) 的生成树棵数就是 \([x^v]F(x)\)。
接下来考虑将加法换为二进制运算后怎样处理,我们还是将每条边看作一个幂级数 \(x^w\),那么与之前唯一的区别是,原来幂级数 \(x^u\) 和 \(x^v\) 乘积的贡献会累加到 \(x^{u+v}\) 上,即加法卷积,现在 \(x^u\) 和 \(x^v\) 的乘积则会累加到 \(x^{u|v}\)(或者 \(x^{u\&v}\),或 \(x^{u\operatorname{xor}v}\))上,即二进制卷积。看到二进制卷积我们很自然地想到一个东西——FWT,因此如果题目中的 \(\oplus\) 只是 \(\operatorname{and}\) 或 \(\operatorname{or}\) 或 \(\operatorname{xor}\) 的话,那么我们就可以一遍 FWT,再求出基尔霍夫矩阵解出每种权值的行列式,再 IFWT 回去求出所有的 \(cnt_k\)。而现在对于新定义的 \(\oplus\) 运算,虽然它每一位的运算规律都不同,但由于它们彼此之间互相独立,并且都是二进制运算,因此 FWT 对于该运算依然适用,具体来说对于每一位如果它是 ^
就按照 FWTxor/IFWTxor 的套路合并,&,|
也同理,这样即可求出最终的 \(cnt_k\)。
时间复杂度 \(2^wn^3\),可以通过此题。记得模上一个大质数,为了防止冲突我取了 \(993244853\)(请求出生成树个数模 \(993244853\) 等于 \(0\) 的概率(大雾))。
const int MOD=993244853;
const int INV2=496622427;
const int MAXN=70;
const int MAXV=1<<12;
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;
}
void add(int &x,int v){((x+=v)>=MOD)&&(x-=MOD);}
int n,m,k;char s[14];
int a[MAXN+5][MAXN+5][MAXV+5],b[MAXV+5];
void FWT(int *a,int type){
for(int i=2,lg=0;lg<k;i<<=1,++lg){
for(int j=0;j<(1<<k);j+=i)
for(int l=0;l<(i>>1);l++){
if(s[lg]=='|'){
if(~type) add(a[(i>>1)+j+l],a[j+l]);
else add(a[(i>>1)+j+l],MOD-a[j+l]);
} else if(s[lg]=='&'){
if(~type) add(a[j+l],a[(i>>1)+j+l]);
else add(a[j+l],MOD-a[(i>>1)+j+l]);
} else {
int X=a[j+l],Y=a[(i>>1)+j+l];
if(~type) a[j+l]=(X+Y)%MOD,a[(i>>1)+j+l]=(X-Y+MOD)%MOD;
else a[j+l]=1ll*INV2*(X+Y)%MOD,a[(i>>1)+j+l]=1ll*INV2*(X-Y+MOD)%MOD;
}
}
}
}
int getdet(int x){
int sgn=1;
for(int i=1;i<n;i++){
int t=i;
for(int j=i+1;j<n;j++) if(a[j][i][x]) t=j;
for(int j=i;j<n;j++) swap(a[i][j][x],a[t][j][x]);
if(t^i) sgn=-sgn;
int iv=qpow(a[i][i][x],MOD-2);
for(int j=i+1;j<n;j++){
int mul=1ll*(MOD-iv)*a[j][i][x]%MOD;
for(int l=i;l<n;l++) a[j][l][x]=(a[j][l][x]+1ll*mul*a[i][l][x])%MOD;
}
} int res=(sgn+MOD)%MOD;
// for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) printf("%d%c",a[i][j][x]," \n"[j==n]);
for(int i=1;i<n;i++) res=1ll*res*a[i][i][x]%MOD;
return res;
}
int main(){
scanf("%d%d%s",&n,&m,s);k=strlen(s);
for(int i=1,u,v,w;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);--u;--v;
add(a[u][v][w],MOD-1);add(a[v][u][w],MOD-1);
add(a[u][u][w],1);add(a[v][v][w],1);
}
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) FWT(a[i][j],1);
// for(int i=0;i<(1<<k);i++){
// for(int u=1;u<n;u++) for(int v=1;v<n;v++)
// printf("%d%c",a[u][v][i]," \n"[v==n]);
// printf("\n");
// }
for(int i=0;i<(1<<k);i++) b[i]=getdet(i)/*,printf("%d\n",b[i])*/;
FWT(b,-1);for(int i=(1<<k)-1;~i;i--) if(b[i]) return printf("%d\n",i),0;
// assert(114514^1919810^114514^1919810);
puts("-1");
return 0;
}
洛谷 P5406 - [THUPC2019]找树(FWT+矩阵树定理)的更多相关文章
- 洛谷4208 JSOI2008最小生成树计数(矩阵树定理+高斯消元)
qwq 这个题目真的是很好的一个题啊 qwq 其实一开始想这个题,肯定是无从下手. 首先,我们会发现,对于无向图的一个最小生成树来说,只有当存在一些边与内部的某些边权值相同的时候且能等效替代的时候,才 ...
- 洛谷 P3377 【模板】左偏树(可并堆)
洛谷 P3377 [模板]左偏树(可并堆) 题目描述 如题,一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或 ...
- 洛谷 1938 [USACO09NOV]找工就业Job Hunt
洛谷 1938 [USACO09NOV]找工就业Job Hunt 题目描述 Bessie is running out of money and is searching for jobs. Far ...
- 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)
洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...
- 洛谷P3377 【模板】左偏树(可并堆) 题解
作者:zifeiy 标签:左偏树 这篇随笔需要你在之前掌握 堆 和 二叉树 的相关知识点. 堆支持在 \(O(\log n)\) 的时间内进行插入元素.查询最值和删除最值的操作.在这里,如果最值是最小 ...
- 洛谷P3434 [POI2006]KRA-The Disks(线段树)
洛谷题目传送门 \(O(n)\)的正解算法对我这个小蒟蒻真的还有点思维难度.洛谷题解里都讲得很好. 考试的时候一看到300000就直接去想各种带log的做法了,反正不怕T...... 我永远只会有最直 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 【题解】洛谷P1350 车的放置(矩阵公式推导)
洛谷P1350:https://www.luogu.org/problemnew/show/P1350 思路 把矩阵分为上下两块N与M 放在N中的有i辆车 则放在M中有k-i辆车 N的长为a 宽为 ...
- 【洛谷3822】[NOI2017] 整数(线段树压位)
题目: 洛谷 3822 分析: 直接按题意模拟,完了. 将每次加 / 减拆成不超过 \(32\) 个对单独一位的加 / 减. 考虑给一个二进制位(下称「当前位」)加 \(1\) 时,如果这一位本来就是 ...
随机推荐
- wget命令8种实用用法
大家好,我是良许. wget 是一个可以从网络上下载文件的免费实用程序,它的工作原理是从 Internet 上获取数据,并将其保存到本地文件中或显示在你的终端上. 这实际上也是大家所使用的浏览器所做的 ...
- 初学python-day2 字符串格式化1
- Redis 高阶数据类型重温
今天这个专题接着上一篇 Redis 的基本数据类型 继续讲解剩下的高阶数据类型:BitMap.HyperLogLog 和 GEO hash.这些数据结构的底层也都是基于我们前面说的 5 种 基本类型, ...
- SharkCTF2021 Classic_Crypto_king2
crypto类题. 题面如下: 前面的代码给出了原理:后面的字符串第一行是print出的key,第二行是密文. 加密原理是,首先对table进行乱序处理,然后将明文flag按照(顺序table--&g ...
- docker逃逸漏洞复现(CVE-2019-5736)
漏洞概述 2019年2月11日,runC的维护团队报告了一个新发现的漏洞,SUSE Linux GmbH高级软件工程师Aleksa Sarai公布了影响Docker, containerd, Podm ...
- [no_code][Alpha]事后分析
$( "#cnblogs_post_body" ).catalog() 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们要解决的 ...
- [火星补锅] 水题大战Vol.2 T2 && luogu P3623 [APIO2008]免费道路 题解
前言: 如果我自己写的话,或许能想出来正解,但是多半会因为整不出正确性而弃掉. 解析: 这题算是对Kruskal的熟练运用吧. 要求一颗生成树.也就是说,最后的边数是确定的. 首先我们容易想到一个策略 ...
- 一从二主IIC连接调试
最近有个项目需要实现快速开机出摄像头预览(2s内),但是我的板子linux上的qt应用起来都要10s左右了,于是在硬件上增加了一个屏驱芯片TW8836,这是一个mcu,可以直接获取摄像头数据送到lcd ...
- 第05课 OpenGL 3D空间
3D空间: 我们使用多边形和四边形创建3D物体,在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体. 在上节课的内容上作些扩展,我们现在开始生成真正的3D对象,而不是象前两节课中那样3D ...
- WPF_02_XAML
XAML(Extensible Application Markup Language的简写)是用于实例化.NET对象的标记语言.XAML对于WPF不是必须的. XAML基础 XAML标准: XAML ...