HDU - 5909 Tree Cutting 树形dp + fwt 优化异或卷积和
2017-10-15 11:50
453 查看
题意:
给你一颗n个结点树,每个结点的权值为 vi (0<=vi<m,m<=210),定义一个子树的权值为这个子树节点的权值的异或。分别求权值为[0,m−1]的子树的个数mod(109+7)
思路:
考虑dp[x][val] 表示以x为根,异或权值为val的子树的个数。
显然转移时有:
dp[x][val]=dp[x][val]+∑i⊕jdp[x][i]∗dp[v][j] (卷积异或和).
如果朴素的枚举两个再加上dfs,复杂度为n3.
上面这个卷积异或和的过程我们考虑用fwt优化. O(mlogm)
所以总的复杂度为 O(nmlogm)
给你一颗n个结点树,每个结点的权值为 vi (0<=vi<m,m<=210),定义一个子树的权值为这个子树节点的权值的异或。分别求权值为[0,m−1]的子树的个数mod(109+7)
思路:
考虑dp[x][val] 表示以x为根,异或权值为val的子树的个数。
显然转移时有:
dp[x][val]=dp[x][val]+∑i⊕jdp[x][i]∗dp[v][j] (卷积异或和).
如果朴素的枚举两个再加上dfs,复杂度为n3.
上面这个卷积异或和的过程我们考虑用fwt优化. O(mlogm)
所以总的复杂度为 O(nmlogm)
#include<bits/stdc++.h> 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;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { ll x=a[i+j],y=a[i+j+d]; a[i+j] = (x+y)%mod,a[i+j+d] = (x-y+mod)%mod; } } void UFWT_XOR(ll *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++) { ll x=a[i+j],y=a[i+j+d]; a[i+j]=(x+y)*inv%mod,a[i+j+d]=((x-y)*inv % mod+mod)%mod; } } void 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; }
相关文章推荐
- Hdu 5909 Tree Cutting(fwt优化异或卷积)
- HDU - 5909 Tree Cutting 树形DP+fwt优化 或点分治(待补)
- HDU 5909 Tree Cutting(树形DP+FWT)
- HDU 5909 Tree Cutting [树形dp+FWT]【动态规划+数学】
- HDU 5909 Tree Cutting (树形dp+FWT)
- HDU 5909 Tree Cutting (点分治+树形DP|FWT+树形DP)
- HDU 5909 Tree Cutting(FWT+树形DP)
- HDU5909 Tree Cutting(树形DP + FWT)
- HDU 5909 Tree Cutting 树形DP+快速沃尔什变换
- hdu5909 Tree Cutting 【树形dp + FWT】
- [树形DP FWT] HDU 5909 Tree Cutting
- hdu 5909 Tree Cutting [树形DP fwt]
- 【HDU 5909】 Tree Cutting (树形依赖型DP+点分治)
- HDU 5909 FWT 加速集合异或
- hdu 5745 La Vie en rose(dp + bitset优化)
- HDU 3920【状态压缩DP +优化】
- 解题报告:HDU_5909:Tree Cutting 树上FWT
- HDU 5909 Tree Cutting 动态规划 快速沃尔什变换
- HDU 5909 Tree Cutting
- Hdu 5909 Tree Cutting