题面传送门

首先看到这道题你必须要有一个很清楚的认识:这题新定义的 \(\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+矩阵树定理)的更多相关文章

  1. 洛谷4208 JSOI2008最小生成树计数(矩阵树定理+高斯消元)

    qwq 这个题目真的是很好的一个题啊 qwq 其实一开始想这个题,肯定是无从下手. 首先,我们会发现,对于无向图的一个最小生成树来说,只有当存在一些边与内部的某些边权值相同的时候且能等效替代的时候,才 ...

  2. 洛谷 P3377 【模板】左偏树(可并堆)

    洛谷 P3377 [模板]左偏树(可并堆) 题目描述 如题,一开始有N个小根堆,每个堆包含且仅包含一个数.接下来需要支持两种操作: 操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或 ...

  3. 洛谷 1938 [USACO09NOV]找工就业Job Hunt

    洛谷 1938  [USACO09NOV]找工就业Job Hunt 题目描述 Bessie is running out of money and is searching for jobs. Far ...

  4. 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)

    洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...

  5. 洛谷P3377 【模板】左偏树(可并堆) 题解

    作者:zifeiy 标签:左偏树 这篇随笔需要你在之前掌握 堆 和 二叉树 的相关知识点. 堆支持在 \(O(\log n)\) 的时间内进行插入元素.查询最值和删除最值的操作.在这里,如果最值是最小 ...

  6. 洛谷P3434 [POI2006]KRA-The Disks(线段树)

    洛谷题目传送门 \(O(n)\)的正解算法对我这个小蒟蒻真的还有点思维难度.洛谷题解里都讲得很好. 考试的时候一看到300000就直接去想各种带log的做法了,反正不怕T...... 我永远只会有最直 ...

  7. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  8. 【题解】洛谷P1350 车的放置(矩阵公式推导)

    洛谷P1350:https://www.luogu.org/problemnew/show/P1350 思路 把矩阵分为上下两块N与M 放在N中的有i辆车 则放在M中有k-i辆车 N的长为a   宽为 ...

  9. 【洛谷3822】[NOI2017] 整数(线段树压位)

    题目: 洛谷 3822 分析: 直接按题意模拟,完了. 将每次加 / 减拆成不超过 \(32\) 个对单独一位的加 / 减. 考虑给一个二进制位(下称「当前位」)加 \(1\) 时,如果这一位本来就是 ...

随机推荐

  1. STM32单片机的学习方法(方法大体适用所有开发版入门)

    1,一款实用的开发板. 这个是实验的基础,有时候软件仿真通过了,在板上并不一定能跑起来,而且有个开发板在手,什么东西都可以直观的看到,效果不是仿真能比的.但开发板不宜多,多了的话连自己都不知道该学哪个 ...

  2. SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多

    关于封面:晚饭后回自习室的路上 Easyexcel 官方文档 Easyexcel | github 前言 最近也是在写的一个小练习中,需要用到这个.趁着这次就将写个整合的Demo给大家. 希望能够让大 ...

  3. c 不同类型的指针

    今天看到了一个问题:c里面,不同类型的指针是否可以互指呢?也就是不同类型的指针之间是否可以互相赋值,我想了想,对于32位机子而言,所有类型的指针都是4Byte(64位就是8Byte,这里只讨论32位) ...

  4. 输出单层结点 牛客网 程序员面试金典 C++ Python

    输出单层结点 牛客网 程序员面试金典 C++ Python 题目描述 对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表. 给定二叉树的根结点指针TreeNode* root,以及链表上 ...

  5. IELTS6 2020.7 Translation

    原文 <三国演义>(The Romance of the ThreeKingdoms)是中国一部著名的历史小说,写于十四世纪.这部文学作品以三国时期的历史为背景,描写了从公元二世纪下半叶到 ...

  6. 使用vsftpd 搭建ftp服务

    ftp 基础服务器基础知识 ftp有三种登录方式.匿名登录(所有用户).本地用户.虚拟用户(guest). FTP工作模式 主动模式:服务端从20端口主动向客户端发起链接. 控制端口21:数据传输端口 ...

  7. 动手个性化设置自己的 IntelliJ IDEA

    前言 IDEA 是一个智能开发工具,每个开发者的使用习惯不同,如何个性化自己的IDEA? 我们可以通过 Settings 功能来设置. Settings文件是 IDEA 的配置文件,通过它可以设置主题 ...

  8. Jmeter下载安装(一)

    一.JMeter介绍       JMeter使用了不同技术和协议,是一款可以进行配置和执行负载测试.性能测试和压力测试的工具.负载测试.性能测试和压力测试概念: 负载测试: 这类测试使系统或者应用程 ...

  9. Navicat for MySQL 批量执行多个 SQL 文件

    文件合并 type *.sql >> aaa.sql 执行sql文件 右键点击数据库

  10. 组件通过props属性传值

    组件之间的传值 组件是一个单独功能模块的封装,有属于自己的data和methods,一个组件的 data 选项必须是一个函数 为什么必须是函数:因为只有当data是函数时,不同实例调用同一个组件时才会 ...