Triple(详细揭秘)

Triple

那这题很牛了

直接做每一位有 \(m\) 个选项的

记号如下 : \(n\) 是数组个数,\(d\) 是数组中每个数的个数,\(a_{i,j}\) 是第 \(i\) 个数组中的第 \(j\) 个数,\(c(i,j)\) 是做 FWT 的时候从 \(i\) 转移到 \(j\) 的系数,\(F_i\)\(\sum\limits_j d_jx^{a_{i,j}}\)

直接考虑如何算出 \([x^r]\prod\limits_i FWT(F_i)\);

首先我们考虑暴力 FWT,FWT 之后的 \(x^r\) 系数就等于 \(\prod\limits_{i=1}^n \sum\limits_{j=1}^m c(a_{i,j},r)d_j\)

我们考虑如何快速算这个东西,因为异或矩阵全是 \(\pm 1\),所以对 \(d_jx^{a_{i,j}}\) 做 FWT 之后得到的东西的每一项系数都是形如 \(\pm d_j\) 的,也就是说每个数组分别 FWT 之后每一位都只有 \(2^m\) 种取值

我们只要知道在这 \(n\) 个数组里面每一种都有多少就可以通过 \(2^m\) 次快速幂算出来这个玩意

我们把每个取值压成一个二进制位,如果 \(d_i\) 系数是 \(1\)\(k\) 的第 \(i\) 位为 \(0\),否则是 \(1\),设 \(f_k\) 表示这个玩意的出现次数

事实上就是如果 \(k\) 的第 \(j\) 位为 \(0\),则限制 \(c(a_{i,j},r)=-1\),反之 \(c(a_{i,j},r)=1\)

我们把 \(f\) 看做未知数,用 \(2^m\) 个方程去做它,有一个想法是枚举一个 \(\{1,2,3 \dots m\}\) 的子集 \(T\),设 \(g_{i,T}=\oplus_{j \in T} a_{i,j}\),我们直接对 \(\sum\limits_{i=1}^n x^{g_{i,T}}\) 进行 FWT,设为 \(P_T\)

这样的意义在于 \([x^r]P_T=\sum\limits_{i=1}^n c(g_{i,T},r)=\sum\limits_{i=1}^n \prod\limits_{j \in T} c(a_{i,j},r)\)

而对于 \(f\) 来说可以写成 \(\sum\limits_{i=0}^{2^m-1} f_i \prod\limits_{j \in T}(-1)^{i_j}\)(这里 \(i_j\) 表示 \(i\) 的第 \(j\) 位)

我们肯定可以轻松求出这个式子的值,而且容易发现后面的式子相当于对 \(f\) FWT 之后 \(x^T\) 的系数,所以枚举 \(T\) 算刚才那个就能求出 \(f\) 了,复杂度 \(O((m+k)2^{m+k}+nm2^m)\)

把题目中的 \(xor\) 换成其他简单位运算也是一样的,比如换成 \(and\),那么变成 \(k\) 的第 \(j\) 位为 \(0\),则限制 \(c(a_{i,j},r)=0\),反之 \(c(a_{i,j},r)=1\)

\(\sum\limits_{i=1}^n \prod\limits_{j \in T} c(a_{i,j},r)\) 对于 \(f\) 来说就会变成 \(\sum\limits_{i=0}^{2^m-1} f_i \prod\limits_{j \in T}[i_j \not =0]\)

注意到这个就是 \(f\) 经过矩阵 \(\begin{bmatrix}1 &1\\0 &1\end{bmatrix}\) 转移得到的第 \(T\) 项,类似的乘回它的逆矩阵就好了

贴个代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
const llt mod=998244353;
const llt N=100100,M=1<<17,S=1<<3; 
llt n,m,k,c[4],a[N][4],s[M+1],f[M+1][S+1],ans[M+1];
llt qpow(llt x,llt y)
{
    llt res=1;
    while(y)
    {
        if(y&1) res=res*x%mod;
        x=x*x%mod;y>>=1;
    }
    return res;
}
struct Matrix
{
    llt c[2][2];
    Matrix(){memset(c,0,sizeof(c));}
    Matrix(llt A,llt B,llt C,llt D){c[0][0]=A,c[0][1]=B,c[1][0]=C,c[1][1]=D;}
};
const Matrix Xor(1,1,1,mod-1),iXor(499122177,499122177,499122177,499122176);
void fwt(llt* num,Matrix mat,llt Len)
{
    for(int L=1;L<(1<<Len);L<<=1)
    {
        for(int i=0;i<(1<<Len);i+=2*L)
            for(int j=i;j<i+L;j++)
            {
                llt s0=num[j],s1=num[j+L];
                num[j]=(mat.c[0][0]*s0+mat.c[1][0]*s1)%mod;
                num[j+L]=(mat.c[0][1]*s0+mat.c[1][1]*s1)%mod;
            }
    }
}
int main()
{
    #ifdef LOCAL
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    scanf("%lld%lld%lld%lld%lld",&n,&k,&c[1],&c[2],&c[3]);m=3;
    for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&a[i][1],&a[i][2],&a[i][3]);
    for(int i=0;i<(1<<m);i++)
    {
        for(int j=1;j<=n;j++)
        {
            llt res=0;
            for(int u=0;u<m;u++) if((i>>u)&1) res^=a[j][u+1];
            s[res]++;
        }
        fwt(s,Xor,k);for(int j=0;j<(1<<k);j++) f[j][i]=s[j],s[j]=0;
    }
    for(int i=0;i<(1<<k);i++) 
    {
        fwt(f[i],iXor,m);ans[i]=1;
        for(int j=0;j<(1<<m);j++)
        {
            llt res=0;
            for(int u=0;u<m;u++)
            {
                if((j>>u)&1) res=res-c[u+1];
                else res=res+c[u+1];
            }
            res=(res%mod+mod)%mod;
            ans[i]=ans[i]*qpow(res,f[i][j])%mod;
        }
    }
    fwt(ans,iXor,k);for(int i=0;i<(1<<k);i++) printf("%lld ",ans[i]);
    return 0;
}
posted @ 2025-08-27 18:05  wang54321  阅读(27)  评论(0)    收藏  举报