洛谷 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\) 时,如果这一位本来就是 ...
随机推荐
- jquery-无缝滚动
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【c++ Prime 学习笔记】第6章 函数
6.1 函数基础 函数定义包括:返回类型.函数名字.由0个或多个形参组成的列表以及函数体 通过调用运算符()来执行函数,它作用于一个表达式,该表达式是函数或函数指针.圆括号内是一个逗号隔开的实参列表, ...
- [no code][scrum meeting] Alpha 9
项目 内容 会议时间 2020-04-15 会议主题 OCR验收 会议时长 15min 参会人员 OCR组成员 $( "#cnblogs_post_body" ).catalog( ...
- 运维常用python库&模块
sutil:是一个跨平台库(https://github.com/giampaolo/psutil)能够实现获取系统运行的进程和系统利用率(内存,CPU,磁盘,网络等),主要用于系统监控,分析和系统资 ...
- 如何使用原生的Ribbon
什么是Ribbon 之前分析了如何使用原生的Feign,今天我们来研究 Netflix 团队开发的另外一个类库--Ribbon. Ribbon 和 Feign 有很多相似的地方,首先,它们本质上都是 ...
- 基于屏幕空间的实时全局光照(Real-time Global Illumination Based On Screen Space)
目录 Reflective Shadow Maps(RSM) RSM 的重要性采样 RSM 的应用与缺陷 Screen Space Ambient Occulsion(SSAO) SSAO Blur ...
- Python 类似 SyntaxError: Non-ASCII character '\xc3' in file
Python 类似 SyntaxError: Non-ASCII character '\xc3' in file 产生这个问题的原因: python 的默认编码文件是ACSII,而编辑器将文件保存为 ...
- Vue2高级原理
<div id="app"> <input type="text" v-model="username"> ...
- telnet IP 端口 的作用
测试远程服务器的端口是否开启
- shell 脚本二进制安装mysql
以下脚本的手动安装连接:https://www.cnblogs.com/leihongnu/p/12581793.html [ #/bin/bash#脚本安装 mysql,上传安装包至 /rootcd ...