zoukankan      html  css  js  c++  java
  • 快速沃尔什变换(FWT) 与 快速莫比乌斯变换 与 快速沃尔什变换公式推导

    后面的图片将会告诉:

    如何推出FWT的公式tf

    如何推出FWT的逆公式utf

    用的是设系数,求系数的方法!

    =========================================================

    以一种高度思考

    http://picks.logdown.com/posts/179290-fast-walsh-hadamard-transform

    加和乘的定义

    大小为1时的公式

    https://blog.csdn.net/zhshrs/article/details/54838466

    证明

    https://blog.csdn.net/john123741/article/details/76576925

    写成

    or

    tf(A)=(tf(A0),tf(A1)+tf(A0))

    utf(A)=(utf(A0),utf(A1)-utf(A0))

    and

    tf(A)=(tf(A0)+tf(A1),tf(A1))

    utf(A)=(utf(A0)-utf(A1),utf(A1))

    xor

    tf(A)=(tf(A0)+tf(A1),tf(A0)-tf(A1))

    utf(A)=(1/2*(utf(A0)+utf(A1)),1/2*(utf(A0)-utf(A1)))

    更好记忆一点

    对于or,and

    0 = 0 or 0 对应 or tf(A0)[utf(A0)]

    1 = 1 and 1 对应 and tf(A1)[utf(A1)]

    =================================

    and or xor 二进制操作

    0~2^(k-1)-1时,最高位为0

    2^(k-1)~2^k-1时,最高位为1

    e.g.

    000

    001

    010

    011

    ----

    100

    101

    110

    111

    P.S.:

    FFT和FWT,两者虽然实现方法都是内容分半(二分),但是其本质原理不同。

    FFT: http://www.cnblogs.com/zwfymqz/p/8244902.html

    快速莫比乌斯变换

    study from :

    https://yhx-12243.github.io/OI-transit/records/vijos%20%234.html

    适用于and or,xor 行不通

    FMT写法和FWT是一样的,两者考虑问题角度不一样。

    https://www.luogu.org/problemnew/show/P4717

    存储函数地址

        void (*addr1[3])(ll a[])={fwt1,fwt2,fwt3};
        void (*addr2[3])(ll a[])={ufwt1,ufwt2,ufwt3};

    also can use (int type)=1ll*...

    注意当数字范围为[0,x]

    遍历范围 [0,z) tot=2*x(大于any i op j, 其中i,j in [0,x])

    而数组开z大小

    对于代码中的tot,要写成2^k的形式,

    否则如写成tot,e.g. tot=9,  8(i)+3(j)>9。

    对应好记忆

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=998244353;
     14 const int maxn=(1<<17)*2;   ///any n or <2n
     15 
     16 /**
     17 补全为2^k
     18 **/
     19 
     20 ll aa[maxn],bb[maxn],a[maxn],b[maxn];
     21 int tot;
     22 ll mod_inv_2=(mod+1)/2;
     23 
     24 ///or
     25 void fwt1(ll *a)
     26 {
     27     int cnt_pre,cnt_cur,i,j;
     28     for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     29         for (i=0;i<tot;i+=cnt_cur)
     30             for (j=0;j<cnt_pre;j++)
     31                 (a[i+j+cnt_pre]+=a[i+j])%=mod;
     32 }
     33 
     34 void ufwt1(ll *a)
     35 {
     36     int cnt_pre,cnt_cur,i,j;
     37     for (cnt_pre=tot>>1,cnt_cur=tot;cnt_pre>0;cnt_pre>>=1,cnt_cur>>=1)
     38 //    for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     39         for (i=0;i<tot;i+=cnt_cur)
     40             for (j=0;j<cnt_pre;j++)
     41                 (a[i+j+cnt_pre]-=a[i+j]-mod)%=mod;
     42 }
     43 
     44 ///and
     45 void fwt2(ll *a)
     46 {
     47     int cnt_pre,cnt_cur,i,j;
     48     for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     49         for (i=0;i<tot;i+=cnt_cur)
     50             for (j=0;j<cnt_pre;j++)
     51                 (a[i+j]+=a[i+j+cnt_pre])%=mod;
     52 }
     53 
     54 void ufwt2(ll *a)
     55 {
     56     int cnt_pre,cnt_cur,i,j;
     57     for (cnt_pre=tot>>1,cnt_cur=tot;cnt_pre>0;cnt_pre>>=1,cnt_cur>>=1)
     58 //    for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     59         for (i=0;i<tot;i+=cnt_cur)
     60             for (j=0;j<cnt_pre;j++)
     61                 (a[i+j]-=a[i+j+cnt_pre]-mod)%=mod;
     62 }
     63 
     64 ///xor
     65 void fwt3(ll *a)
     66 {
     67     int cnt_pre,cnt_cur,i,j;
     68     ll x;
     69     for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     70         for (i=0;i<tot;i+=cnt_cur)
     71             for (j=0;j<cnt_pre;j++)
     72             {
     73                 x=a[i+j];
     74                 a[i+j]=(a[i+j]+a[i+j+cnt_pre])%mod;
     75                 a[i+j+cnt_pre]=(x-a[i+j+cnt_pre]+mod)%mod;
     76             }
     77 }
     78 
     79 void ufwt3(ll *a)
     80 {
     81     int cnt_pre,cnt_cur,i,j;
     82     ll x;
     83     for (cnt_pre=tot>>1,cnt_cur=tot;cnt_pre>0;cnt_pre>>=1,cnt_cur>>=1)
     84 //    for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     85         for (i=0;i<tot;i+=cnt_cur)
     86             for (j=0;j<cnt_pre;j++)
     87             {
     88                 x=a[i+j];
     89                 a[i+j]=(a[i+j]+a[i+j+cnt_pre])*mod_inv_2%mod;
     90                 a[i+j+cnt_pre]=(x-a[i+j+cnt_pre]+mod)*mod_inv_2%mod;    ///x-
     91             }
     92 }
     93 
     94 int main()
     95 {
     96     int n,i,j;
     97     scanf("%d",&n);
     98     tot=1<<n;
     99     for (i=0;i<tot;i++)
    100         scanf("%lld",&aa[i]);
    101     for (i=0;i<tot;i++)
    102         scanf("%lld",&bb[i]);
    103 
    104 
    105     void (*addr1[3]) (ll a[])={fwt1,fwt2,fwt3};
    106     void (*addr2[3]) (ll a[])={ufwt1,ufwt2,ufwt3};
    107 
    108     for (i=0;i<3;i++)
    109     {
    110         memcpy(a,aa,sizeof(aa));
    111         memcpy(b,bb,sizeof(bb));
    112         (*addr1[i])(a);
    113         (*addr1[i])(b);
    114         for (j=0;j<tot;j++)
    115             a[j]=a[j]*b[j]%mod;
    116         (*addr2[i])(a);
    117         for (j=0;j<tot;j++)
    118             printf("%lld%c",a[j],j==tot-1?'
    ':' ');
    119     }
    120     return 0;
    121 }
    122 /*
    123 0
    124 1000000
    125 1000000
    126 
    127 3
    128 1 1 1 1 1 1 1 1
    129 1 1 1 1 1 1 1 1
    130 */

    对应下方的图片公式推导

    tf  a0+a1  a1-a0

    utf  a1    a0

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const double eps=1e-8;
     12 const ll inf=1e9;
     13 const ll mod=998244353;
     14 const int maxn=(1<<17)*2;   ///any n or <2n
     15 
     16 /**
     17 补全为2^k
     18 **/
     19 
     20 ll aa[maxn],bb[maxn],a[maxn],b[maxn];
     21 int tot;
     22 ll mod_inv_2=(mod+1)/2;
     23 
     24 ///or
     25 void fwt1(ll *a)
     26 {
     27     int cnt_pre,cnt_cur,i,j;
     28     for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     29         for (i=0;i<tot;i+=cnt_cur)
     30             for (j=0;j<cnt_pre;j++)
     31                 (a[i+j+cnt_pre]+=a[i+j])%=mod;
     32 }
     33 
     34 void ufwt1(ll *a)
     35 {
     36     int cnt_pre,cnt_cur,i,j;
     37     for (cnt_pre=tot>>1,cnt_cur=tot;cnt_pre>0;cnt_pre>>=1,cnt_cur>>=1)
     38 //    for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     39         for (i=0;i<tot;i+=cnt_cur)
     40             for (j=0;j<cnt_pre;j++)
     41                 (a[i+j+cnt_pre]-=a[i+j]-mod)%=mod;
     42 }
     43 
     44 ///and
     45 void fwt2(ll *a)
     46 {
     47     int cnt_pre,cnt_cur,i,j;
     48     for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     49         for (i=0;i<tot;i+=cnt_cur)
     50             for (j=0;j<cnt_pre;j++)
     51                 (a[i+j]+=a[i+j+cnt_pre])%=mod;
     52 }
     53 
     54 void ufwt2(ll *a)
     55 {
     56     int cnt_pre,cnt_cur,i,j;
     57     for (cnt_pre=tot>>1,cnt_cur=tot;cnt_pre>0;cnt_pre>>=1,cnt_cur>>=1)
     58 //    for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     59         for (i=0;i<tot;i+=cnt_cur)
     60             for (j=0;j<cnt_pre;j++)
     61                 (a[i+j]-=a[i+j+cnt_pre]-mod)%=mod;
     62 }
     63 
     64 ///xor
     65 void fwt3(ll *a)
     66 {
     67     int cnt_pre,cnt_cur,i,j;
     68     ll x;
     69     for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     70         for (i=0;i<tot;i+=cnt_cur)
     71             for (j=0;j<cnt_pre;j++)
     72             {
     73                 x=a[i+j];
     74                 (a[i+j]+=a[i+j+cnt_pre])%=mod;
     75                 (a[i+j+cnt_pre]-=x-mod)%=mod;   ///-x
     76             }
     77 }
     78 
     79 void ufwt3(ll *a)
     80 {
     81     int cnt_pre,cnt_cur,i,j;
     82     ll x;
     83     for (cnt_pre=tot>>1,cnt_cur=tot;cnt_pre>0;cnt_pre>>=1,cnt_cur>>=1)
     84 //    for (cnt_pre=1,cnt_cur=2;cnt_pre<tot;cnt_pre<<=1,cnt_cur<<=1)
     85         for (i=0;i<tot;i+=cnt_cur)
     86             for (j=0;j<cnt_pre;j++)
     87             {
     88                 x=a[i+j];
     89                 a[i+j]=(a[i+j]+a[i+j+cnt_pre])*mod_inv_2%mod;
     90                 a[i+j+cnt_pre]=(x-a[i+j+cnt_pre]+mod)*mod_inv_2%mod;    ///x-
     91             }
     92 }
     93 
     94 int main()
     95 {
     96     int n,i,j;
     97     scanf("%d",&n);
     98     tot=1<<n;
     99     for (i=0;i<tot;i++)
    100         scanf("%lld",&aa[i]);
    101     for (i=0;i<tot;i++)
    102         scanf("%lld",&bb[i]);
    103 
    104 
    105     void (*addr1[3]) (ll a[])={fwt1,fwt2,fwt3};
    106     void (*addr2[3]) (ll a[])={ufwt1,ufwt2,ufwt3};
    107 
    108     for (i=0;i<3;i++)
    109     {
    110         memcpy(a,aa,sizeof(aa));
    111         memcpy(b,bb,sizeof(bb));
    112         (*addr1[i])(a);
    113         (*addr1[i])(b);
    114         for (j=0;j<tot;j++)
    115             a[j]=a[j]*b[j]%mod;
    116         (*addr2[i])(a);
    117         for (j=0;j<tot;j++)
    118             printf("%lld%c",a[j],j==tot-1?'
    ':' ');
    119     }
    120     return 0;
    121 }
    122 /*
    123 0
    124 1000000
    125 1000000
    126 
    127 3
    128 1 1 1 1 1 1 1 1
    129 1 1 1 1 1 1 1 1
    130 */

    and,or,xor等操作

    C=A@B @为卷积运算(通过两个函数生成第三个函数的一种数学算子)

    目标:tf(C)=tf(A)*tf(B)

    设置tf(X)=(... , ...) 使满足上述条件

    基础部分

    公式推导

     

     验证公式正确性

  • 相关阅读:
    gj10 python socket编程
    自定义Git
    使用GitHub
    标签管理之操作标签
    标签管理之创建标签
    标签管理
    git分支管理之多人协作
    git分支管理之Feature分支
    git分支管理之Bug分支
    git分支管理之分支管理策略
  • 原文地址:https://www.cnblogs.com/cmyg/p/10424145.html
Copyright © 2011-2022 走看看