HDU - 5909 Tree Cutting 树形dp + fwt 优化异或卷积和

题意:

给你一颗n个结点树,每个结点的权值为 vi ( 0<=vi<m,m<=210 ),定义一个子树的权值为这个子树节点的权值的异或。分别求权值为[0,m−1]的子树的个数 mod(109+7)

思路:

考虑dp[x][val] 表示以x为根,异或权值为val的子树的个数。

显然转移时有:
dp[x][val]=dp[x][val]+ijdp[x][i]dp[v][j] (卷积异或和).
如果朴素的枚举两个再加上dfs,复杂度为 n3 .

上面这个卷积异或和的过程我们考虑用fwt优化. O(mlogm)
所以总的复杂度为 O(nmlogm)

#include

using namespace std;
const int maxn = 1e3 + 5;
const int maxm = 1500;
const int maxval = (1 << 10);
const int mod = 1e9+7;
typedef long long ll;
int n,m;
int v[maxn];
ll ans[maxm],mid[maxm];
ll dp[maxn][maxm];
vector<int>vt[maxn];

ll qmod (ll a,ll b)
{
    ll res = 1;
    while(b)
    {
        if(b&1) res = res * a % mod;
        b >>= 1;
        a = a * a %mod;
    }
    return res;
}
ll inv = qmod(2,mod-2);

void FWT_XOR(ll  *a,int n)
{
    for(int d=1;d1)
        for(int m=d<<1,i=0;ifor(int j=0;jvoid UFWT_XOR(ll *a,int n)
{
    for(int d=1;d1)
        for(int m=d<<1,i=0;ifor(int j=0;jvoid solve_XOR(ll *a,ll *b,int maxl)
{
    FWT_XOR(a,maxl);
    FWT_XOR(b,maxl);
    for(int i=0;i < maxl;i++) a[i]=a[i]*b[i] %mod;
    UFWT_XOR(a,maxl);
}

void dfs(int x,int f)
{
    dp[x][v[x]] = 1;
    for(int i = 0;i < vt[x].size();++i)
    {
        int v = vt[x][i];
        if(v == f) continue;
        dfs(v,x);
        for(int i = 0;i < m;++i)
            mid[i] = dp[x][i];
        solve_XOR(dp[x],dp[v],maxval);
        for(int i = 0;i < m;++i)
            dp[x][i] = (dp[x][i] + mid[i]) % mod;
    }
    for(int i = 0;i < m;++i)
        ans[i] = (ans[i] + dp[x][i]) %mod;
}
int main()
{
    int _;
    cin >> _;
    while(_--)
    {
        scanf("%d %d",&n,&m);
        for(int i = 1;i <= n;++i)
            scanf("%d",&v[i]),vt[i].clear();
        for(int i = 1;i < n;++i)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            vt[x].push_back(y);
            vt[y].push_back(x);
        }
        memset(dp,0,sizeof dp);
        memset(ans,0,sizeof ans);
        dfs(1,-1);

        for(int i = 0;i < m;++i)
            printf("%lld%c",ans[i],i == m - 1? '\n':' ');
    }
    return 0;
}

你可能感兴趣的:(树形dp,FWT)