Tree Cutting HDU - 5909

题意:

一个无根树,n个点,n-1条边,每个节点有一个权值,一棵树的权值就是其节点(包含本身及其子节点)的权值的异或和;求价值为[0,m)的树有多少颗?(所谓的树其实就是原连通图的任意子图)
n<=1000
m<=2102^{10}210

题解:

不难想到树形dp
设dp[u][i]表示以u节点为根的价值为i的树的数量
能得到转移方程:
dp[u][j⨁k]=dp[u][j⨁k]+dp[u][j]∗d[v][k]dp[u][j\bigoplus k]=dp[u][j\bigoplus k]+dp[u][j]*d[v][k]dp[u][j⨁k]=dp[u][j⨁k]+dp[u][j]∗d[v][k]
u是v的父亲节点
不过这个式子直接算会超时,复杂度为O(n∗m∗m)O(n*m*m)O(n∗m∗m)
我们将式子变形:
dp[u][i]=∑j∗k=idp[u][j]∗d[v][k]dp[u][i]=\sum_{j*k=i}dp[u][j]*d[v][k]dp[u][i]=∑j∗k=i​dp[u][j]∗d[v][k]
这个就长得很像FWT
没错,就可以用FWT优化了
每次将dp[u][]和dp[v][]卷起来,并记录当前节点u为根的答案
优化后复杂度为O(nmlogm)O(nmlogm)O(nmlogm)

代码:

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...);
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef ONLINE_JUDGE
#elsestartTime = clock ();freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int P=1e9+7;
const int mod=1e9+7;
const int maxn1=(1<<13);
#define int long long
int val[1020];
vector<int>vec[2000];
int ans[maxn1];
int tmp[maxn1];
int dp[1020][maxn1];
int n,m;
/*
设dp[i][j]:表示以i为根的子树中异或和为j的数量
*/
int qpow(int a,int b){int ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans%mod;
}
void FWT(int x[],int t1,int t2,int len)
{const ll inv2= qpow(2,mod-2);for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=(i<<1))for(int k=0;k<i;k++){ll p=x[j+k],q=x[i+j+k];if(t1==0) x[i+j+k]=(q+P+t2*p)%P;  //orelse if(t1==1) x[j+k]=(p+P+t2*q)%P;   //andelse if(t1==2)   //xor{x[j+k]=(p+q)%P*(t2<0?inv2:1)%P;x[i+j+k]=(p+P-q)%P*(t2<0?inv2:1)%P;}     }
}
void say(int a[],int len){for(int i=0;i<len;i++){printf("a[%d]=%d\n",i,a[i]);}}
void solve(int a[],int b[],int len){//  say(a,len);
//  say(b,len);FWT(a,2,1,len);FWT(b,2,1,len);for(int i=0;i<len;i++)a[i]=a[i]*b[i]%mod;FWT(a,2,-1,len);
}
void dfs(int u,int fa){dp[u][val[u]]=1;for(auto v:vec[u]){if(v==fa)continue;dfs(v,u);for(int j=0;j<m;j++){tmp[j]=dp[u][j];}solve(dp[u],dp[v],m);for(int j=0;j<m;j++){dp[u][j]=(tmp[j]+dp[u][j])%mod;}}for(int i=0;i<m;i++){ans[i]=(ans[i]+dp[u][i])%mod;}
}
signed main()
{//    rd_test();int t;read(t);while(t--){read(n,m);for(int i=1;i<=n;i++)read(val[i]);for(int i=1;i<n;i++){int u,v;read(u,v);vec[u].push_back(v);vec[v].push_back(u);}memset(dp,0,sizeof dp);memset(ans,0,sizeof ans);dfs(1,1);for(int i=0;i<m;i++){if(i==0)cout<<ans[i];else cout<<" "<<ans[i];}cout<<endl;for(int i=1;i<=n;i++)vec[i].clear();}//Time_test();
}
/**/

Tree Cutting HDU - 5909相关推荐

  1. fwt优化+树形DP HDU 5909

    1 //fwt优化+树形DP HDU 5909 2 //见官方题解 3 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ 4 5 #include ...

  2. bzoj 3391: [Usaco2004 Dec]Tree Cutting网络破坏

    3391: [Usaco2004 Dec]Tree Cutting网络破坏 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 296  Solved: 2 ...

  3. bzoj3391[Usaco2004 Dec]Tree Cutting网络破坏*

    bzoj3391[Usaco2004 Dec]Tree Cutting网络破坏 题意: 给一棵树,问去掉哪个点后可以使剩下的每个子树大小都小于等于节点总数的一半.n≤10000. 题解: dfs的时候 ...

  4. hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...

  5. HDU.5909.Tree Cutting(树形DP FWT/点分治)

    题目链接 \(Description\) 给定一棵树,每个点有权值,在\([0,m-1]\)之间.求异或和为\(0,1,...,m-1\)的非空连通块各有多少个. \(n\leq 1000,m\leq ...

  6. Tree Cutting POJ - 2378(树形DP)

    题意:有n个谷仓有n-1条路连接,问最少删除哪几个点才能使得删除点后得到的连通图的加点数不大于n/2. 分析:求树的重心的变形题,poj3107的简单版,一遍dfs从叶子到根转移找出找到以每个节点为根 ...

  7. 【POJ - 2378】Tree Cutting(树形dp,树的重心变形)

    题干: After Farmer John realized that Bessie had installed a "tree-shaped" network among his ...

  8. 点分治问题 ----------- HDU6881 Tree Cutting or 2020杭电多校第10场 [点分治+思维]

    题目链接 题目大意: 给定nnn个节点的树,问删除尽可能小的点使得树的直径不超过KKK,输出最小删除的点数,(1<=k<=n<=3e5)(1<=k<=n<=3e5) ...

  9. CodeForces - 1118F1 Tree Cutting (Easy Version)(树形dp)

    题目链接:点击查看 题目大意:给定n个点,每个点的权值分别对应颜色:0:无颜色,1:红色,2:蓝色,现在需要切割边,使切割后的两个部分不能出现红色和蓝色掺杂的部分,也就是说两个部分必须只能各自含有一个 ...

最新文章

  1. java super实例_java Super 用法详解及实例代码
  2. [ An Ac a Day ^_^ ] CodeForces 468A 24 Game 构造
  3. WebBrowser内存泄露
  4. 转 框架页有Frame、Iframe、Frameset 3个标记,初学者容易将三者混淆,下面分别讲解三者的区别。...
  5. commons-lang的FastDateFormat性能测试
  6. #if, #ifdef, #ifndef, #else, #elif, #endif的用法
  7. Spring4.x(15)---SpringEL-三目运算
  8. [翻译]Adobe Flash Player 11新特性
  9. NMEA0183协议中的GGA语句解析
  10. Mysql 分组求和
  11. java se11.0.1安装_jdk11下载安装及环境变量配置
  12. 有了PDA手持终端,仓库再也不愁盘点了
  13. 【蓝牙】室内外定位技术-钛斗™星地融合定位系统
  14. 仿小米商城SpringBoot+Vue全栈项目开发实战文档
  15. 机器学习入门:准备知识笔记(pandas)之一
  16. HC-SuK070-C【通信口配置】之CAN
  17. 知识图谱与古希腊人物关系
  18. 毫无保留!珍藏多年的“学习”网站...
  19. 快消行业订货系统解决方案
  20. java-php-python-ssm在校大学生健康状况信息管理系统计算机毕业设计

热门文章

  1. 中国代工厂的困惑:把大牌t恤卖到99块3件,还会有人买吗?
  2. 今天,滴滴被爆亏损109亿,需裁员2000多人,哪些员工会被裁掉?
  3. Boosting集合算法详解(一)
  4. rabbitmq入门_Rabbit MQ 入门
  5. windows挂载ext4_使用 UEFI 双启动 Windows 和 Linux | Linux 中国
  6. c++与java,有什么区别?
  7. 类选项html 最后无距离,各种距离 一览无遗
  8. android 强制下线功能,Android学习之基础知识八—Android广播机制实践(实现强制下线功能)...
  9. python实用脚本 知乎_停课不停学|38 个免费 Python 项目合集,从小白到老司机!...
  10. python123动物重量排序_Python爬虫图片学习(一)