FWT快速沃尔什变换

Fast Walsh-Hadamard Transform 就是用于解决一类卷积问题的方法。

时间复杂度nlogn,求解的内容如下

可以用于求解数组A和数组B异或后能得到哪些数之类的问题(暴力枚举是n^2的复杂度)

 1 void FWT(int a[],int n)  
 2 {  
 3     for(int d=1;d<n;d<<=1)  
 4         for(int m=d<<1,i=0;i<n;i+=m)  
 5             for(int j=0;j<d;j++)  
 6             {  
 7                 int x=a[i+j],y=a[i+j+d];  
 8                 //a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;  
 9                 //xor:
10                 a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod;  
11                 //and:a[i+j]=x+y;  
12                 //or:a[i+j+d]=x+y;  
13             }  
14 }  
15   
16 void UFWT(int a[],int n)  
17 {  
18     for(int d=1;d<n;d<<=1){
19         for(int m=d<<1,i=0;i<n;i+=m) { 
20             for(int j=0;j<d;j++)  
21             {  
22                 int x=a[i+j],y=a[i+j+d];  
23                 //a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
24                 //xor:
25                 a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
26                 //and:a[i+j]=x-y;  
27                 //or:a[i+j+d]=y-x;  
28             }
29         }  
30     }
31     
32 }  
33 void solve(int a[],int b[],int n)  
34 {  
35     //求解C[i]=segma(j^k==i?a[j]*b[k]:0),时间复杂度nlogn 
36     //可用于求解n个数两两异或能得到哪些数,c[i]!=0表示该数能求解得到。
37     FWT(a,n);  
38     FWT(b,n);  
39     for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod;  
40     UFWT(a,n);  
41 }  

猜你喜欢

转载自www.cnblogs.com/Charlies/p/9469733.html