[关闭]
@MLEAutoMaton 2019-02-11T14:06:17.000000Z 字数 2221 阅读 561

FWT总结

学习笔记 题单


引入

一般的多项式乘法是这样子的:

但是如果我们将这个乘法式子里面的+号变换一下变成其他的运算符号呢?

其中可以取

这个时候FFT和NTT就没有什么用了...

前人的智慧是无穷的!

考虑一个神奇的算法:FWT(快速沃尔什变化)

or卷积

先从最容易的or卷积下手.

我们考虑他给出的式子:

我们将i,j按照二进制拆开,发现这其实相当于是一个状压dp?

然后就可以直接搞了(因为这个二进制有传递的效果.)

上面是废话...

考虑怎么求这个玩意:

用一个式子:

这个证明不会(真的菜)

然后只要把这个套进去就可以了(或还是比较简单)

然后就好了啊.qwq

and卷积

这个东西的话其实和or没有什么比较大的区别:

xor卷积

证明的坑以后会补的.

IFWT

考虑FFT我们怎么做的?

肯定是先把(这个是逐位乘)

然后再还原对吧.

所以FWT也需要还原.

然后既然怎么来的推出来了,怎么回去也就会了不是吗?

代码实现

  1. namespace cpp1{
  2. int A[N],B[N],limit;
  3. void init(){
  4. limit=len;
  5. for(int i=0;i<limit;i++)A[i]=a[i];
  6. for(int i=0;i<limit;i++)B[i]=b[i];
  7. }
  8. void FMT(int *A,int limit,int opt){
  9. for(int i=1;i<limit;i<<=1)
  10. for(int j=0;j<limit;j++)
  11. if(i&j)
  12. if(opt==1)A[j]=(A[j]+A[j^i])%Mod;
  13. else A[j]=(A[j]+Mod-A[j^i])%Mod;
  14. }
  15. void solve(){
  16. FMT(A,limit,1);FMT(B,limit,1);
  17. for(int i=0;i<limit;i++)A[i]=(1ll*A[i]*B[i])%Mod;
  18. FMT(A,limit,-1);
  19. for(int i=0;i<limit;i++)printf("%d%c",A[i],i==limit-1?'\n':' ');
  20. }
  21. }
  22. namespace cpp2{
  23. int A[N],B[N],limit;
  24. void init(){
  25. limit=len;
  26. for(int i=0;i<limit;i++)A[i]=a[i];
  27. for(int i=0;i<limit;i++)B[i]=b[i];
  28. }
  29. void FWTand(int *a,int limit,int opt){
  30. for(int i=1;i<limit;i<<=1)
  31. for(int j=0,p=i<<1;j<limit;j+=p)
  32. for(int k=0;k<i;k++)
  33. if(opt==1)a[j+k]=(a[j+k]+a[i+j+k])%Mod;
  34. else a[j+k]=(a[j+k]-a[i+j+k]+Mod)%Mod;
  35. }
  36. void solve(){
  37. FWTand(A,limit,1);FWTand(B,limit,1);
  38. for(int i=0;i<limit;i++)A[i]=(1ll*A[i]*B[i])%Mod;
  39. FWTand(A,limit,-1);
  40. for(int i=0;i<limit;i++)printf("%d%c",A[i],i==limit-1?'\n':' ');
  41. }
  42. }
  43. namespace cpp3{
  44. int A[N],B[N],limit,inv2=499122177;
  45. void init(){
  46. limit=len;
  47. for(int i=0;i<limit;i++)A[i]=a[i];
  48. for(int i=0;i<limit;i++)B[i]=b[i];
  49. }
  50. void FWTxor(int *a,int limit,int opt){
  51. for(int i=1;i<limit;i<<=1)
  52. for(int p=i<<1,j=0;j<limit;j+=p)
  53. for(int k=0;k<i;k++){
  54. int X=a[j+k],Y=a[i+j+k];
  55. a[j+k]=(X+Y)%Mod;a[i+j+k]=(X+Mod-Y)%Mod;
  56. if(opt==-1){
  57. a[j+k]=1ll*a[j+k]*inv2%Mod;
  58. a[i+j+k]=1ll*a[i+j+k]*inv2%Mod;
  59. }
  60. }
  61. }
  62. void solve(){
  63. FWTxor(A,limit,1);FWTxor(B,limit,1);
  64. for(int i=0;i<limit;i++)A[i]=(1ll*A[i]*B[i])%Mod;
  65. FWTxor(A,limit,-1);
  66. for(int i=0;i<limit;i++)printf("%d%c",A[i],i==limit-1?'\n':' ');
  67. }
  68. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注