Other polynomial algorithm Portal:
[Polynomial algorithm] (Part 1) FFT Fast Fourier Transform Learning Notes
[Polynomial algorithm] (Part 2) NTT fast number theory transformation study notes
[Polynomial algorithm] (Part 5) Divide and Conquer FFT study notes
\ (4.Extreme-FWT \)
FWT\((Fast\ Walsh-Hadamard\ Transform)\)
Chinese name: Fast Walsh Transform
(Fast Wrong-Answer Transform)
\ (Q: \) has finished poured? \ (FWT \) , then what is? We are now able to handle any situation polynomial multiplication, and also to do this?
\(A:\)I do not want to learn ah, did not back down
Although we can quickly find \ (C = A * B, C_k = \ sum_ {i + j = k} A_i * B_j \) , but now let you ask \ (C = A \ oplus B , C_k = \ sum_ {I \ Oplus J = K} A_i * B_j \) , where \ (\ Oplus \) represents a bit operation symbol such as \ (| (or), \ & (and), \ Land (XOR) \) , how do you do it?
Then he went to the \ (FWT \) debut.
Let us for a \ (FWT \) is \ (3 \) formsEmotional understandingDiscuss
\ (Part1 - FWT (or) \)
Set \ (A_0, A_1 \) respectively of length \ (n = 2 ^ x \ ) polynomial \ (A \) of the front and rear halves.
Firstly, \ (FWT (A) \) is calculated:
\[ FWT(A)=\begin{cases} (FWT(A_0),FWT(A_0)+FWT(A_1))&(n>1)\\ A&(n=1) \end{cases} \]
Wherein \ ((A, B) \ ) represents a two polynomials are connected.
So \ (n = 1 \) it is clearly right, border thing.
As \ (n> 1 \) How to understand the situation?
For \ (A_0 \) and \ (A_0 \) in two subscripts \ (or \) up a little still \ (A_0 \) in (the highest bit is binary \ (0 \) , is the first half), then contribute to the first half only.
For \ (A_1 \) and \ (A_1 \) in two numbers, empathy only contribute to the second half.
For \ (A_0 \) and \ (A_1 \) two numbers, thinking \ (FWT (A) _k \ ) sense, are:
\[FWT(A)_k=\sum_{i|k=k}A_i\]
Because when \ (i | k = k, j | k = k \) when there is \ ((I | J) | K = K \) , satisfies \ (the FWT \) may be combined properties.
Since then \ (A_1 \) subscript binary MSB is \ (1 \) , so \ (or \) together generated only contribution to the second half.
Contribution is \ (A_0 \) to \ (A_1 \) contribution ( \ (A_1 \) has contributed over yourself, do not add).
Then the formula is quite clear.
Meanwhile The \ (FWT (A) \) meaning easily find \ (the FWT (A_0 A_1 +) = the FWT (A_0) + the FWT (A_1) \) .
Then prove \ (FWT (A | B) = FWT (A) * FWT (B) \) (guarantee \ (or \) correctness convolution answer, or else \ (FWT \) there is no use).
When \ (n = 1 \) , the property is clearly established
When \ (n> 1 \) when:
\[ \begin{equation} \begin{split} FWT(A|B)=&FWT((A|B)_0,(A|B)_1)\\ &=FWT(A_0|B_0,A_0|B_1+A_1|B_0+A_1|B_1)\\ &=(FWT(A_0|B_0),FWT(A_0|B_0+A_0|B_1+A_1|B_0+A_1|B_1))\\ &=(FWT(A_0)*FWT(B_0),FWT(A_0)*FWT(B_0)+FWT(A_0)*FWT(B_1)\\ &+FWT(A_1)*FWT(B_0)+FWT(A_1)*FWT(B_1))\\ &=(FWT(A_0)*FWT(B_0),(FWT(A_0)+FWT(A_1))*(FWT(B_0)+FWT(B_1)))\\ &=(FWT(A_0)*FWT(B_0),FWT(A_0+A_1)*FWT(B_0+B_1)))\\ &=(FWT(A_0),FWT(A_0+A_1))*(FWT(B_0),FWT(B_0+B_1))\\ &=FWT(A)*FWT(B) \end{split} \end{equation} \]
That the mathematical induction, this property holds.
So \ (or \) is \ (FWT \) is very good ~ ~ wrote the code behind.
\(Part2--FWT(and)\)
\ (and \) of \ (FWT \) on and \ (or \) is very similar to the.
Since \ (A_0 \) and (A_1 \) \ highest bit different, so \ (and \) after only (A_0 \) \ contribute.
Similar \ (or \) can be obtained \ (FWT (A) \) is calculated:
\[ FWT(A)=\begin{cases} (FWT(A_0)+FWT(A_1),FWT(A_1))&(n>0)\\ A(n=0) \end{cases} \]
As proved not write, and (or \) \ similar,Says trouble。
\ (Part3 - FWT (xor) \)
mostfanThe \ (xor \) to the
To be honest, the Internet to find a lot of \ (Blog \) , do not seem to give construction method,Then I will not ah
When you are looking for someone fairy her laws
The first is \ (FWT (A) \) is calculated:
\[ FWT(A)=\begin{cases} (FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1))&(n>0)\\ A(n=0) \end{cases} \]
Look at all sick, How it's constructed ah \ (QAQ \)
So, by definition, is easy to prove \ (FWT (A \ pm B ) = FWT (A) \ pm FWT (B) \)
Since \ (the FWT \) is a linear combination, to satisfy the above properties.
Then \ (FWT (A \ land B ) = FWT (A) * FWT (B) \)
This can be proved by mathematical induction,See References
\ (Q: \) and so on ...... is not what's missing? \ (FWT \) how to change it back later?
\(A:\)This is not simpleThe next process is the \ (IFWT \) up!
\(Part4--IFWT(or)\)
\ (Emm ... \) As \ (IFWT \) it is very simple, you can reverse the conversion.
(Is not this nonsensical)
Then for \ (or \) is \ (IFWT \) , there is before you consider \ (FWT \) equation:
\ [FWT (A) = (FWT (A_0), FWT (A_0) + FWT (A_1)) \]
That is:
\ [FWT (A) _0 = FWT (A_0), FWT (A) _1 = FWT (A_0) + FWT (A_1) \]
\ [FWT (A_0) = FWT (A) _0, FWT (A_1) = FWT (A_0) -FWT (A) _1 = FWT (A) _0-FWT (A) _1 \]
At this time, the definition of \ (IFWT (A) _0 = the FWT (A_0), IFWT (A) the FWT _1 = (A_1) \) , has:
\[ IFWT(A)=\begin{cases} (IFWT(A_0),IFWT(A_0)-IFWT(A_1))&(n>0)\\ A&(n=0) \end{cases} \]
\ (En ... \) really simple
\(Part5--IFWT(and)\)
Similar \ (or \) is \ (IFWT \) , can be obtained directly:
\[ IFWT(A)=\begin{cases} (IFWT(A_0)-IFWT(A_1),IFWT(A_1))&(n>0)\\ A(n=0) \end{cases} \]
Similar to the process here is not to repeat them. .
\ (Part IFWT (chorus) \)
\ (xor \) is \ (IFWT \) as simple as a surprise.
By definition was:
\ [\ Begin {cases} FWT (A) _0 = FWT (A_0) + FWT (A_1) \\ FWT (A) _1 = FWT (A_0) -FWT (A_1) \ end {cases} \]
Solution of the equation is simple.
Finally there is:
\[ IFWT(A)=\begin{cases} (\frac{IFWT(A_0)+IFWT(A_1)}2,\frac{IFWT(A_0)-IFWT(A_1)}2)&(n>0)\\ A&(n=0) \end{cases} \]
Finally finished
Then the next step isFigure write wordsSee the definition of a process to write the code:
Here in order to save the amount of codes \ (6 \) functions written together (because substantially similar frame).
P4717 [template] Fast Walsh Transform
Code:
#include <cstdio>
#include <cstring>
typedef long long ll;
const int Mod=998244353,Inv2=(Mod+1)>>1;//Inv2 2在mod998244353下的逆元
int n,a[1<<17],b[1<<17],as[1<<17],bs[1<<17];
void FWT(int *A,int op,int t)
//op [1/-1][FWT/IFWT]
//t [1,2,3][or/and/xor]
{
for(int i=2;i<=n;i<<=1)//i 区间长度
for(int j=0,m=i>>1;j<n;j+=i)//j 区间左端 m 区间大小一半
for(int k=0;k<m;++k)//k 正在算第几个数
if(t==1)A[j+m+k]=((ll)A[j+m+k]+A[j+k]*op+Mod)%Mod;
else if(t==2)A[j+k]=((ll)A[j+k]+A[j+m+k]*op+Mod)%Mod;
else
{
int A0=A[j+k],A1=A[j+m+k];
A[j+k]=(ll)(A0+A1)*(op==1?1:Inv2)%Mod;
A[j+m+k]=(ll)(A0-A1+Mod)*(op==1?1:Inv2)%Mod;
}
}
int main()
{
scanf("%d",&n),n=1<<n;
for(int i=0;i<n;++i)scanf("%d",&as[i]);
for(int i=0;i<n;++i)scanf("%d",&bs[i]);
for(int t=1;t<=3;++t)//分别计算or/and/xor
{
memcpy(a,as,sizeof(int)*n);
memcpy(b,bs,sizeof(int)*n);
FWT(a,1,t),FWT(b,1,t);
for(int i=0;i<n;++i)a[i]=a[i]*1LL*b[i]%Mod;
FWT(a,-1,t);
for(int i=0;i<n;++i)printf("%d%c",a[i],i==n-1?'\n':' ');
}
return 0;
}
Code should be easy to understand, not explained.
I can only say: \ (FWT \)Nice backNice write.
References :( \ (Dalao \ TQL \) )
FWT Fast Walsh Transform Study Notes - Small konjac yyb
A little learning and thinking about the Fast Walsh Transform (FWT) of -ACMLCZH