ABC367G 题解

题意

给定正整数 N,M,K 和一个非负整数序列 A=(A1,A2,,AN)

对于一个非空的序列 B=(B1,B2,,B|B|),我们定义它的得分为:

  • |B|M 的倍数:(B1B2B|B|)K
  • 否则为 0

这里 运算表示按位异或。

找到序列 A2N1 个非空子序列的得分之和,对 998244353 取模。

首先考虑转化这个 K 次方,发现对于异或和很难用组合方面的知识转化,所以直接考虑对于每个 x,求 fx 表示有多少长度为 M 倍数的子序列异或和等于 x。总答案为 x(fx×xk),问题转化为求出 f 数组。

这个问题的形式很 FWT,更进一步,我们有 n 个幂级数 Hi,第 i 个幂级数 FWT 前只有 0Ai 的位置有值,因为有 M 的限制,所以我们考虑把它的系数变成一个矩阵 Y,因为 FWT 是一个线性变换,所以系数是整数还是矩阵都没有影响。

将每个 Hi FWT 一遍后得到 Hi,将其点乘起来并 IFWT 一遍后就得到了 fi 了,时间复杂度 O(nVlogV),其中 VAi 的值域。

考虑优化上面这个做法,容易发现每个 Hi 中只有 Ai0 的位置有值,分别是 YI,其中 I 是单位矩阵。根据 xor 运算的 FWT 的性质,Hi=j(1)popcount(i & j)Hj,则可以发现 Hi 只有两种情况:(I+Y)(IY)。所以最后点乘后得到的 fi 一定为 (I+Y)a(IY)b,且 a+b=N

先用 O(NM)dp 预处理出矩阵的值(其实根本不用推出这个矩阵),只需要记 dp1[i][j]dp2[i][j],然后用下面的递推式推导即可:

{dp1[i+1][j]=dp1[i][j]+dp1[i][(j1+M)modM]dp2[i+1][j]=dp2[i][j]dp2[i][(j1+M)modM]

再推一个 Gi=j=0M1dp1[i][j]×dp2[Ni][(Mj)modM],这样得到了 (I+Y)i(IY)Ni 的值了。

接下来考虑快速得到这个 a,根据 FWT 的性质,如果 popcount(x & y) 为偶数,那么 y 就给 fx 贡献了一个 (I+Y)。所以计算 fxa,实际上是在计数有多少 Ai 使得 popcount(Ai & x) 为偶数。考虑使用 FWT 加速这一过程,记 Fi,j 表示有多少 x,使得 popcount(i,x)mod2=j,初始值 Fx,0=cnt(x)(因为初始的时候相当于序列长度只有 1),其中 cnt(x)=i=1N[x=Ai]

基于 FWT 蝴蝶变换时的性质,当两边进行合并时刚好有 1 位不同,所以有转移(记 x=j+k,y=i+j+k,其中 i,j,k 为蝴蝶变换时的三个下标):

{Fx,0=Fx,0+Fy,0Fx,1=Fx,1+Fy,1Fy,0=Fx,0+Fy,1Fy,1=Fx,1+Fy,0

最后将 fiGFi,0 即可,IFWT 一遍就得到原来的 fi 了,总时间复杂度 O(NM+VlogV)

代码是贺的,就不放了。

posted @   CTHOOH  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示