P6569 [NOI Online #3 提高组] 魔法值 题解

news/2025/1/5 22:40:40/文章来源:https://www.cnblogs.com/peiwenjun/p/18651290

题目描述

\(n\) 个城市, \(m\) 条无向边,记第 \(i\) 个点第 \(j\) 天的魔法值为 \(f_{i,j}\)

给定 \(f_{i,0}\) ,此后每天某个城市的魔法值,等于与它相邻的城市上一天魔法值的异或和,即:

\[f_{u,j}=\bigoplus_{(u,v)\in E}f_{v,j-1}\\ \]

\(q\) 次询问,给定 \(a_i\) ,求 \(f_{1,a_i}\)

数据范围

  • \(1\le n,q\le 100,1\le m\le\frac{n(n-1)}2\)
  • \(1\le a_i\lt 2^{32},0\le f_{i,0}\lt 2^{32}\)

时间限制 \(\texttt{1s}\) ,空间限制 \(\texttt{512MB}\)

分析

矩阵快速幂技巧大杂烩。

方法一

\(F_j=\begin{bmatrix}f_{1,j}&\cdots&f_{n,j}\\\end{bmatrix}\)\(G\) 为转移矩阵,则 \(F_j=F_0\times G^j\)

这里 \(\times\) 定义为 \((\oplus,\times)\) 矩阵乘法,即:

\[C_{n,l}=A_{n,m}\times B_{m,l}\\ c_{i,j}=\bigoplus_{1\le k\le m}a_{i,k}\times b_{k,j}\\ \]

由于矩阵乘法需要满足结合律,第二个运算符对第一个运算符需要满足左分配律。比如常见的 \((+,\times),(\min,+)\) 矩阵,我们有:

\[(a+b)\times c=a\times c+b\times c\\ \min(a,b)+c=\min(a+c,b+c)\\ \]

这是因为,对于 \((\star,\odot)\) 矩阵乘法:

\[(ABC)_{i,j}=\bigstar\big((\bigstar a_{i,k}\odot b_{k,l})\odot c_{l,j}\big)\\ \]

结合律意味着可以打开内层括号,即 \(\odot\)\(\star\) 有左分配律。

非常遗憾, \(\times\)\(\oplus\) 并不具有左分配律。

但是本题还有一个特殊条件: \(G\) 中元素仅有 \(0\)\(1\)

读者可以自行验证 \((a\oplus b)\times c=a\times c\oplus b\times c\)\(c\in\{0,1\}\) 时成立,换言之,\(C\)\(01\) 矩阵时, \((\oplus,\times)\) 矩阵乘法符合结合律


直接做矩阵快速幂,时间复杂度 \(\mathcal O(qn^3\log a)\)

但是向量乘矩阵单次 \(\mathcal O(n^2)\) ,如果预处理 \(G^{2^j}\) ,询问时直接将 \(a_i\) 二进制分解,用答案向量乘上 \(a_i\) 二进制下为 \(1\) 的位对应的矩阵即可,时间复杂度 \(\mathcal O(n^3\log a+qn^2\log a)\)

#include<bits/stdc++.h>
#define ui unsigned int
using namespace std;
int m,n,q,x,y;
struct vec
{ui v[105];
}o;
struct mat
{ui v[105][105];
}g[32];
vec operator*(vec a,mat b)
{static vec c;for(int i=1;i<=n;i++){c.v[i]=0;for(int j=1;j<=n;j++) c.v[i]^=a.v[j]*b.v[j][i];}return c;
}
mat operator*(mat a,mat b)
{static mat c;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){c.v[i][j]=0;for(int k=1;k<=n;k++) c.v[i][j]^=a.v[i][k]*b.v[k][j];}return c;
}
int main()
{scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++) scanf("%u",&o.v[i]);for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),g[0].v[x][y]=g[0].v[y][x]=1;for(int i=1;i<32;i++) g[i]=g[i-1]*g[i-1];while(q--){scanf("%d",&x);vec cur=o;for(int i=0;i<32;i++) if(x>>i&1) cur=cur*g[i];printf("%u\n",cur.v[1]);}return 0;
}
方法二

\(01\) 矩阵做矩阵快速幂,怎么能少 bitset 优化呢?

在域 \(\{0,1\}\) 下,可以将乘法视为按位与:

mat operator*(mat a,mat b)
{mat c;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)c.v[i][j]^=a.v[i][k]&b.v[k][j];return c;
}

但是如果将第二维压入 bitset ,它和下述写法等价:

mat operator*(mat a,mat b)
{mat c;for(int i=1;i<=n;i++)for(int k=1;k<=n;k++)if(a.v[i][k]) c.v[i]^=b.v[k];return c;
}

暴力矩阵快速幂的时间复杂度 \(\mathcal O(\frac{qn^3\log a}w)\) ,已经足够通过了,这也是下面代码中展示的做法。

如果硬要套向量乘矩阵的 \(\texttt{trick}\) ,那就需要将 \(F_0\) 拆位,时间复杂度 \(\mathcal O(\frac{n^3\log a}w+\frac{32qn^2\log a}w)\) 。由于 \(n\)\(32\) 数量级相差不大,因此没有必要。

#include<bits/stdc++.h>
#define ui unsigned int
using namespace std;
int m,n,q,x,y;
ui res,f[105];
struct mat
{bitset<105> v[105];mat(){for(int i=1;i<=n;i++) v[i].reset();}
}g[32];
mat operator*(mat a,mat b)
{mat c;for(int i=1;i<=n;i++)for(int k=1;k<=n;k++)if(a.v[i][k]) c.v[i]^=b.v[k];return c;
}
int main()
{scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++) scanf("%u",&f[i]);for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),g[0].v[x][y]=g[0].v[y][x]=1;for(int i=1;i<32;i++) g[i]=g[i-1]*g[i-1];while(q--){scanf("%d",&x),x--,res=0;mat cur=g[0];for(int i=0;i<32;i++) if(x>>i&1) cur=cur*g[i];for(int i=1;i<=n;i++) if(cur.v[i][1]) res^=f[i];printf("%u\n",res);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/863645.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FreeNAS 11.2-U6 简易上手指南

NAS是一个网络附属存储管理器,简单的可以理解为一个可以将数据存储至网络设备的服务。 NAS一般都会支持数据冗余、日志、压缩以及校验等功能。 国内最出名的应该就是群晖的系统了,当然我们这里主要讲解的是FreeNAS。 FreeNAS是一个基于FreeBSD进行二次开发的开源NAS系统,其支…

WhyNotWin11(win11检测工具)

微软官方Windows11检测工具写的太烂,第三方作者开发了一个,软件给每一项都标注了功能,通过了显示绿色,没通过显示红色。Windows目前不支持6、7代处理器。另外,主板不支持加密TPM2.0加密的也不行,不过这个TPM加密,估计后面会妥协,哦不,所有的都会妥协。获取地址:https…

vue基础语法

1、插值语法 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>插值语法</title><script src="../vu/js/vue.js"></script> </head> <body><!--插值语法示…

Luogu P4287 SHOI2011 双倍回文 题解 [ 紫 ] [ manacher ]

manacher 经典结论。双倍回文:回文子串结论的经典应用。 结论 先放本题最关键的结论:一个字符串本质不同的回文子串最多只有 \(n\) 个。 考虑如何证明: 假设我们一个一个地在当前字符串(黑色部分)的结尾加入字符(红色部分),那么会出现如下情况:显然,加入红色字符后,…

傲梅轻松备份(系统备份还原)v7.4.1 技术师增强版

傲梅轻松备份是由傲梅官方推出的电脑上一键备份系统工具,有着业界最快的备份速度,能够瞬间将电脑上的系统备份下来,方便用户下次系统一键还原。傲梅轻松备份专业版专业解决用户的备份系统不会、磁盘备份不会、文件备份太麻烦等等各种问题,简化了整个备份的流程,加快了备份…

Python多分类Logistic回归详解与实践

在机器学习中,Logistic回归是一种基本但非常有效的分类算法。它不仅可以用于二分类问题,还可以扩展应用于多分类问题。本文将详细介绍如何使用Python实现一个多分类的Logistic回归模型,并给出详细的代码示例。在机器学习中,Logistic回归是一种基本但非常有效的分类算法。它…

【STC8H】STC8 系列单片机低功耗延时方法

STC8 单片机低功耗延时方法 单片机延时通常方法就是跑while循环,但在低功耗要求下可以利用定时唤醒方式使MCU在延时期间睡眠,降低功耗。以STC8G1K08为例: 寄存器 WKTCH^8为使能,其余15位用于控制唤醒时间。并且在唤醒后系统会继续从掉电语句的下一句执行。延时计算 按照公式…

C盘注册表优化清理工具!Wise Registry Cleaner v11.1.9.724

Wise Registry Cleaner是一款优化电脑性能的软件,通过清理注册表中的无效和过时信息来提升计算机运行速度。它能快速扫描并安全清理垃圾文件,同时优化PC。软件具备一键撤销更改和注册表备份功能,确保操作安全。最新版本改进了清理规则,增加了优化项目,并解决了特定软件兼容…

winrar(解压工具-含电脑版和手机版)

winrar,全球使用人数最多解压工具 winrar 烈火汉化无广告版(含电脑版和手机版),一款在官方原版的基础上注册破/解winrar64位去广告版,安装即可使用,不需要使用注册码及key文件,非常简单易用,欢迎有需要的朋友们前来下载使用。另:程序容易被杀毒软件误报,但亲测无毒可…

JVM实战—9.线上FGC的几种案例

大纲 1.如何优化每秒十万QPS的社交APP的JVM性能(增加S区大小 + 优化内存碎片) 2.如何对垂直电商APP后台系统的FGC进行深度优化(定制JVM参数模版) 3.不合理设置JVM参数可能导致频繁FGC(优化反射的软引用被每次YGC回收) 4.线上系统每天数十次FGC导致频繁卡顿的优化(大对象问题) 5…

Unity 中一些常见的富文本标签

Unity 支持的富文本标签主要用于在 Text 和 TextMeshPro 中格式化和控制文本的显示效果。以下是 Unity 中一些常见的富文本标签: 1. 字体样式 <b> 和 </b>: 粗体 <i> 和 </i>: 斜体 <u> 和 </u>: 下划线 <s> 和 </s>: 删除线…

WinMemoryCleaner 电脑内存清理工具

告别卡顿,让电脑飞起来! 这款免费的 RAM 清理器利用了本机 Windows 功能来清理内存区域。有时候,程序在运行结束后并不会释放分配给它的内存,这会导致计算机的性能下降。换句话说,当你使用 Windows Memory Cleaner 来优化内存时,可以继续进行其他工作,而无需浪费时间重新…