zoukankan      html  css  js  c++  java
  • 关于 FWT 的一些理解

    本文作者为 JustinRochester ,转载本文请先与作者本人联系,并注明本文原作者。凡未经允许,私自转载且不注明作者的人,均构成侵权

    规定 (otimes) 为任一位运算,给定数组 (a_n,b_n) ,求数组 (displaystyle c_n=sum_{iotimes j=n}a_ib_j)


    我们假设将数组 (a_n,b_n,c_n) 分别看成一个向量,并对该三个向量进行线性变换。

    (c_n) 的线性变换可逆

    设线性变换分别为 (T_A,T_B,T_C) ,且线性变换后,新数组 (a'_n,b'_n,c'_n) 满足 (c'_n=a'_ncdot b'_n)

    (vec {i'}=T_icdot vec i)

    (vec c=T_C^{-1}vec {c'}=T_C^{-1}(vec {a'}cdot vec {b'})=T_C^{-1}[(T_Avec a)cdot (T_Bvec b)])

    这里的 (vec acdot vec b) 代表对应位相乘

    将满足的等式代入线性变换得 (displaystyle sum_i T_{C(n,i)}c_i=c'_n=a'_ncdot b'_n=sum_p T_{A(n,p)}a_psum_q T_{B(n,q)}b_q)

    代入 (displaystyle c_n=sum_{iotimes j=n}a_ib_j)

    (displaystyle sum_i T_{C(n,i)}sum_{potimes q}a_pb_q=sum_p sum_q T_{B(n,q)} T_{A(n,p)}a_pb_q)

    (displaystyle sum_psum_q T_{C(n,potimes q)}a_pb_q=sum_p sum_q T_{B(n,q)} T_{A(n,p)}a_pb_q)

    约除相同项,我们得到 (displaystyle T_{C(n,potimes q)}=T_{B(n,q)} T_{A(n,p)})

    由于位运算的可按位拆解性,我们得到,对于每一位 (b) ,都有 (displaystyle T_C(n_b,p_botimes_b q_b)=T_B(n_b,q_b) T_A(n_b,p_b))

    又由于二进制每位的取值只有 (0)(1) ,我们对于 (T_i) 只需要构造矩阵 ( left( egin{matrix} T_i(0, 0)&T_i(0, 1) \ T_i(1, 0)&T_i(1, 1) end{matrix} ight) ) ,并且满足上述条件即可

    当然 (T_C) 必须可逆,即 (T_C) 满秩,行列式 (T_C(0, 0)T_C(1, 1)-T_C(0, 1)T_C(1, 0) eq 0)

    当对矩阵中仅有第 (i) 位不同的两个值 (v_l,v_r(v_l<v_r)) 进行计算时,有:

    (left( egin{matrix} v'_l \ v'_r end{matrix} ight)= left( egin{matrix} T_i(0, 0)&T_i(0, 1) \ T_i(1, 0)&T_i(1, 1) end{matrix} ight)cdot left( egin{matrix} v_l \ v_r end{matrix} ight)= left( egin{matrix} T_i(0, 0)v_l+T_i(0, 1)v_r \ T_i(1, 0)v_l+T_i(1, 1)v_r end{matrix} ight))


    (otimes) 为按位或时:构造矩阵 (T_A=T_B=T_C= left( egin{matrix} 1&0 \ 1&1 end{matrix} ight) )

    (q_b=p_b=0)(T_C(n_b, q_bvee p_b)=T_C(n_b, 0)=1=1cdot 1=T_A(n_b,0)cdot T_B(n_b, 0)=T_A(n_b,q_b)cdot T_B(n_b,p_b))

    否则 (T_C(n_b,q_bvee p_b)=T_C(n_b, 1)=n_b=T_A(n_b,q_b)cdot T_A(n_b,p_b))

    由于 ( ext{det }T_C=0-1 eq 0) ,故存在 (T_C^{-1}= left( egin{matrix} 1&0 \ -1&1 end{matrix} ight))

    所以进行 FWT 时,代码如下:

    for(int b=0;1<<b<len;++b) for(int i=0;i<len;++i) if (~i>>b&1) {
    	int j=i^(1<<b);
            a[j]=add(a[j],a[i]);
    }
    

    而进行逆变换 UFWT 时,代码如下:

    for(int b=0;1<<b<len;++b) for(int i=0;i<len;++i) if (~i>>b&1) {
    	int j=i^(1<<b);
            a[j]=dis(a[j],a[i]);
    }
    

    (otimes) 为按位与时:构造矩阵 (T_A=T_B=T_C= left( egin{matrix} 1&1 \ 0&1 end{matrix} ight) )


    (otimes) 为按位异或时:构造矩阵 (T_A=T_B=T_C= left( egin{matrix} 1&1 \ 1&-1 end{matrix} ight) )


    (otimes) 为按位同或时:构造矩阵 (T_A=T_B=T_C= left( egin{matrix} -1&1 \ 1&1 end{matrix} ight) )


    当然,我们知道,单个位的位运算是一个 ({0, 1} imes{0, 1} o{0, 1}) 的二元函数 (f(x,y))

    因此,函数的个数应为 (|{0, 1}^{{0, 1} imes{0, 1}}|=|{0, 1}|^{|{0, 1} imes{0, 1}|}=2^{2 imes 2}=16)

    因此,我们如果能求出这 (16) 种的位运算计算方法,理论上能求解所有的奇葩位运算

    (S) (1otimes 1) (1otimes 0) (0otimes 1) (0otimes 0) (T_A) (T_B) (T_C) (T_C^{-1})
    (0) (0) (0) (0) (0) (left(egin{matrix}1&1 \ 0&0end{matrix} ight)) (left(egin{matrix}1&1 \ 0&0end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight))
    (1) (0) (0) (0) (1) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&-1 \ 0&1end{matrix} ight))
    (2) (0) (0) (1) (0) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&1 \ 1&0end{matrix} ight)) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&-1 \ 0&1end{matrix} ight))
    (3) (0) (0) (1) (1) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight))
    (4) (0) (1) (0) (0) (left(egin{matrix}1&1 \ 1&0end{matrix} ight)) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&-1 \ 0&1end{matrix} ight))
    (5) (0) (1) (0) (1) (left(egin{matrix}1&1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight))
    (6) (0) (1) (1) (0) (left(egin{matrix}1&1 \ 1&-1end{matrix} ight)) (left(egin{matrix}1&1 \ 1&-1end{matrix} ight)) (left(egin{matrix}1&1 \ 1&-1end{matrix} ight)) (left(egin{matrix}{1over 2}&{1over 2} \ {1over 2}&-{1over 2}end{matrix} ight))
    (7) (0) (1) (1) (1) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ -1&1end{matrix} ight))
    (8) (1) (0) (0) (0) (left(egin{matrix}1&1 \ 1&0end{matrix} ight)) (left(egin{matrix}1&1 \ 1&0end{matrix} ight)) (left(egin{matrix}1&1 \ 0&1end{matrix} ight)) (left(egin{matrix}1&-1 \ 0&1end{matrix} ight))
    (9) (1) (0) (0) (1) (left(egin{matrix}1&-1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&-1 \ 1&1end{matrix} ight)) (left(egin{matrix}-1&1 \ 1&1end{matrix} ight)) (left(egin{matrix}-{1over 2}&{1over 2} \ {1over 2}&{1over 2}end{matrix} ight))
    (10) (1) (0) (1) (0) (left(egin{matrix}1&1 \ 1&1end{matrix} ight)) (left(egin{matrix}0&1 \ 1&0end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight))
    (11) (1) (0) (1) (1) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}0&1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ -1&1end{matrix} ight))
    (12) (1) (1) (0) (0) (left(egin{matrix}0&1 \ 1&0end{matrix} ight)) (left(egin{matrix}1&1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight))
    (13) (1) (1) (0) (1) (left(egin{matrix}0&1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ -1&1end{matrix} ight))
    (14) (1) (1) (1) (0) (left(egin{matrix}0&1 \ 1&1end{matrix} ight)) (left(egin{matrix}0&1 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ -1&1end{matrix} ight))
    (15) (1) (1) (1) (1) (left(egin{matrix}0&0 \ 1&1end{matrix} ight)) (left(egin{matrix}0&0 \ 1&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight)) (left(egin{matrix}1&0 \ 0&1end{matrix} ight))

    采用卡诺图化简法得到:

    (T_A=left( egin{matrix} overline{S_3wedge S_2}&(overline{S_1wedge S_0})cdot (-1)^{[S=9]} \ S_3vee S_2&(S_1vee S_0)cdot (-1)^{[S=6]} end{matrix} ight))

    (T_B=left( egin{matrix} overline{S_3wedge S_1}&(overline{S_2wedge S_0})cdot (-1)^{[S=9]} \ S_3vee S_1&(S_2vee S_0)cdot (-1)^{[S=6]} end{matrix} ight))

    (T_C=left( egin{matrix} (-1)^{[S=9]}&(S_2vee S_1)oplus(S_3vee S_0) \ (S_2wedge S_1)oplus(S_3wedge S_0)&(-1)^{[S=6]} end{matrix} ight))

    (displaystyle T_C^{-1}={1over ext{det }T_C} left( egin{matrix} T_{1, 1}&-T_{0, 1} \ -T_{1, 0}&T_{0, 0} end{matrix} ight) =(-{1over 2})^{[S=6vee S=9]}left( egin{matrix} (-1)^{[S=6]}&-(S_2vee S_1)oplus(S_3vee S_0) \ -(S_2wedge S_1)oplus(S_3wedge S_0)&(-1)^{[S=9]} end{matrix} ight))

    inline void updl(ll &a0,ll &a1,int S){
    	bool S0=(S&1),S1=(S>>1&1),S2=(S>>2&1),S3=(S>>3&1);
    	__int128 A0=a0,A1=a1;
    	a0=(S3&S2?0:A0) + (S1&S0?0:A1)*(S==9?-1:1);
    	a1=(S3|S2?A0:0) + (S1|S0?A1:0)*(S==6?-1:1);
    }
    inline void updr(ll &a0,ll &a1,int S){
    	bool S0=(S&1),S1=(S>>1&1),S2=(S>>2&1),S3=(S>>3&1);
    	__int128 A0=a0,A1=a1;
    	a0=(S3&S1?0:A0) + (S2&S0?0:A1)*(S==9?-1:1);
    	a1=(S3|S1?A0:0) + (S2|S0?A1:0)*(S==6?-1:1);
    }
    inline void updi(ll &a0,ll &a1,int S){
    	bool S0=(S&1),S1=(S>>1&1),S2=(S>>2&1),S3=(S>>3&1);
    	__int128 A0=a0,A1=a1;
    	a0=( (S==6?-A0:A0)-( ((S2|S1)^(S3|S0))?A1:0 ) )*(S==6|S==9?-1:1)>>(S==6|S==9);
    	a1=( ( ((S2&S1)^(S3&S0))?-A0:0 )+(S==9?-A1:A1) )*(S==6|S==9?-1:1)>>(S==6|S==9);
    }
    inline void FWT(ll *a,int n,void (*upd)(ll&,ll&,int) ){
    	for(int i=1;i<n;i<<=1) for(int S=0;S<n;++S)
    		if( (~S)&i )
    			upd(a[S],a[S|i],Sta[__builtin_ctz(i)]);
    }
    
  • 相关阅读:
    Binary Tree Maximum Path Sum
    ZigZag Conversion
    Longest Common Prefix
    Reverse Linked List II
    Populating Next Right Pointers in Each Node
    Populating Next Right Pointers in Each Node II
    Rotate List
    Path Sum II
    [Leetcode]-- Gray Code
    Subsets II
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/14589653.html
Copyright © 2011-2022 走看看