FWT(Fast-Walsh-hadamard-Transform)模板+例题

看了大神的博客

http://blog.csdn.net/xuanandting/article/details/70991372 除了排版累死人,别的讲的不错

抄了大神的模板,其实就是递归,只不过用for写的,类似于区间DP。复杂度nlogn

// 下标从0开始 n为2的幂次
void FWT(int a[] ,int n){
    for (int d = 1 ; d < n ; d <<= 1){
        for (int m = d << 1 ,i = 0;i < n ; i+=m){
            for (int j = 0 ; j < d ; j++){
                int x = a[i+j],y = a[i+j+d];
                //xor;
                a[i+j] = (x+y) % mod,a[i+j+d] = (x-y+mod)%mod;
                //and
                //a[i+j]=x+y;
                //or
                //a[i+j+d]=x+y;
            }
        }
    }
}
void UFWT(int a[],int n){
    for (int d = 1 ; d < n ; d<<=1){
        for (int m = d <<1, i = 0; i < n; i+=m){
            for (int j = 0 ; j < d ; j++){
                int x = a[i+j],y = a[i+j+d];
                //xor
                a[i+j] = 1LL*(x+y)*rev2%mod,a[i+j+d] = (1LL*(x-y)*rev2%mod + mod) % mod;
                //and
                //a[i+j] = x-y;
                //or
                //a[i+j+d] = y-x;
            }
        }
    }
}
void solve(int a[],int b[],int n){
    FWT(a,n);
    FWT(b,n);
    for (int i = 0 ; i<n ; i++) a[i]=1LL*a[i]*b[i]%mod;
    UFWT(a,n);
}

又看了一个例题

HDU 5909 这种树DP很常见,如果都是异或值可以这么优化,还有的需要类似FFT的优化。

很裸的DP

 1 #include <bits/stdc++.h>
 2 const int mod = 1e9+7;
 3 int rev2 = (mod+1)/2;
 4 const double ex = 1e-10;
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 // 下标从0开始 n为2的幂次
 8 void FWT(int a[] ,int n){
 9     for (int d = 1 ; d < n ; d <<= 1){
10         for (int m = d << 1 ,i = 0;i < n ; i+=m){
11             for (int j = 0 ; j < d ; j++){
12                 int x = a[i+j],y = a[i+j+d];
13                 //xor;
14                 a[i+j] = (x+y) % mod,a[i+j+d] = (x-y+mod)%mod;
15                 //and
16                 //a[i+j]=x+y;
17                 //or
18                 //a[i+j+d]=x+y;
19             }
20         }
21     }
22 }
23 void UFWT(int a[],int n){
24     for (int d = 1 ; d < n ; d<<=1){
25         for (int m = d <<1, i = 0; i < n; i+=m){
26             for (int j = 0 ; j < d ; j++){
27                 int x = a[i+j],y = a[i+j+d];
28                 //xor
29                 a[i+j] = 1LL*(x+y)*rev2%mod,a[i+j+d] = (1LL*(x-y)*rev2%mod + mod) % mod;
30                 //and
31                 //a[i+j] = x-y;
32                 //or
33                 //a[i+j+d] = y-x;
34             }
35         }
36     }
37 }
38 void solve(int a[],int b[],int n){
39     FWT(a,n);
40     FWT(b,n);
41     for (int i = 0 ; i<n ; i++) a[i]=1LL*a[i]*b[i]%mod;
42     UFWT(a,n);
43 }
44 int a[1300];
45 vector<int> E[1300];
46 int dp[1300][1300];
47 int ans[1300];
48 int tmp[1300];
49 int m;
50 void dfs(int u,int fa){
51     dp[u][a[u]] = 1;
52     for (int i = 0 ; i<E[u].size(); i++){
53         int to = E[u][i];
54         if (to == fa) continue;
55         dfs(to,u);
56         for (int j = 0;j<m; j++){
57             tmp[j] = dp[u][j];
58         }
59         solve(tmp,dp[to],m);
60         for (int j = 0 ; j  < m ;j++){
61             dp[u][j]=(dp[u][j] + tmp[j]) % mod;
62         }
63     }
64     for (int  i = 0 ; i < m; i++){
65         ans[i] = (ans[i] + dp[u][i]) % mod;
66     }
67 }
68 int main()
69 {
70     int t;
71     scanf("%d",&t);
72     while (t--){
73         int n;
74         scanf("%d%d",&n,&m);
75         for (int i = 1; i<=n;i++) E[i].clear();
76         for (int i = 1; i<=n ;i++){
77             scanf("%d",&a[i]);
78         }
79         for (int i=1; i<n ; i++){
80             int u,v;
81             scanf("%d%d",&u,&v);
82             E[u].push_back(v);
83             E[v].push_back(u);
84         }
85         memset(dp,0,sizeof(dp));
86         memset(ans,0,sizeof(ans));
87         dfs(1,0);
88         for (int i = 0; i<m; i++){
89             printf("%d%c",ans[i],i+1==m?'\n':' ');
90         }
91     }
92     return 0;
93 }
View Code

 

posted @ 2017-10-14 18:31  HITLJR  阅读(1717)  评论(0编辑  收藏  举报