题目大意

给定一颗树,每个点有点权,问对于每个m,有多少个联通块的权值异或和为m。

题解

解法1:可以考虑树形dp,设dp[u][i]表示以u为根的子树中u必须选,联通块权值异或值为i的联通块个数。

转移是m^2的,用FWT优化为mlogm,总复杂度nmlogm

解法2:考虑加一个限制:给一个根,根必须选。

我们可以考虑在欧拉序上做文章,考虑到一个欧拉序的位置上,下一位置是它的儿子,如果我们选择了儿子节点,就往下一个位置转移,否则就跨过这颗子树,转移到下一次回溯到这个点的位置。

这个过程可以用dfs实现。

然后考虑选定点的过程,可以用点分治优化,复杂度nmlogn。

从运行常数来看,点分治的常数小一些。

代码(FWT)

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1009
using namespace std;
typedef long long ll;
const int mod=1e9+;
int dp[N][<<],ans[<<],head[N],tot,n,m,a[N],inv,tag[<<],T;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline int power(int x,int y){
int ans=;
while(y){
if(y&)ans=1ll*ans*x%mod;x=1ll*x*x%mod;y>>=;
}
return ans;
}
struct edge{int n,to;}e[N<<];
inline void add(int u,int v){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;}
inline void FWT(int *b,int tag){
// cout<<"(";
for(int i=;i<m;i<<=)
for(int j=;j<m;j+=(i<<))
for(int k=;k<i;++k){
int x=b[j+k],y=b[i+j+k];
b[j+k]=(x+y)%mod;b[i+j+k]=(x-y+mod)%mod;
if(tag)b[j+k]=1ll*b[j+k]*inv%mod,b[i+j+k]=1ll*b[i+j+k]*inv%mod;
}
// cout<<")";
}
void dfs(int u,int fa){
dp[u][a[u]]=;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;
dfs(v,u);
for(int j=;j<m;++j)tag[j]=dp[u][j];
FWT(tag,);FWT(dp[v],);
for(int j=;j<m;++j)tag[j]=1ll*tag[j]*dp[v][j]%mod;
FWT(tag,);
for(int j=;j<m;++j)(dp[u][j]+=tag[j])%=mod;
}
for(int j=;j<m;++j)(ans[j]+=dp[u][j])%=mod;
}
inline void unit(){
memset(ans,,sizeof(ans));
memset(dp,,sizeof(dp));
memset(head,,sizeof(head));
tot=;
}
signed main(){
T=rd();inv=power(,mod-);
while(T--){
n=rd();m=rd();int u,v;unit();
for(int i=;i<=n;++i)a[i]=rd();
for(int i=;i<n;++i){
u=rd();v=rd();add(u,v);add(v,u);
}
dfs(,);
for(int j=;j<m-;++j)printf("%d ",ans[j]);printf("%d\n",ans[m-]);
}
return ;
}

代码(点分治)

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1009
using namespace std;
int size[N],tot,head[N],d[N],a[N],sum,m,n,root,dp[N][<<],ans[<<],T;
bool vis[N];
const int mod=1e9+;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{
int n,to;
}e[N<<];
inline void add(int u,int v){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;}
void getroot(int u,int fa){
d[u]=;size[u]=;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;getroot(v,u);
size[u]+=size[v];d[u]=max(d[u],size[v]);
}
d[u]=max(d[u],sum-size[u]);
if(d[u]<d[root])root=u;
}
void getsize(int u,int fa){
size[u]=;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;getsize(v,u);size[u]+=size[v];
}
}
inline void MOD(int &x){while(x>=mod)x-=mod;}
void calc(int u,int fa){
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;
for(int j=;j<m;++j)MOD(dp[v][j^a[v]]+=dp[u][j]);
calc(v,u);
for(int j=;j<m;++j)MOD(dp[u][j]+=dp[v][j]),dp[v][j]=;
}
}
void solve(int u){
vis[u]=;
dp[u][a[u]]=;calc(u,);
for(int i=;i<m;++i)MOD(ans[i]+=dp[u][i]),dp[u][i]=;
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
root=n+;sum=size[v];
getroot(v,u);getsize(root,);
solve(root);
}
}
inline void unit(){
memset(vis,,sizeof(vis));
memset(head,,sizeof(head));tot=;
}
int main(){
// freopen("in","r",stdin);
// freopen("out","w",stdout);
T=rd();
while(T--){
n=rd();m=rd();unit();int u,v;
for(int i=;i<=n;++i)a[i]=rd();
for(int i=;i<n;++i){u=rd();v=rd();add(u,v);add(v,u);}
root=n+;d[root]=n;sum=n;
getroot(,);getsize(root,);
solve(root);
for(int i=;i<m-;++i)printf("%d ",ans[i]),ans[i]=;
printf("%d\n",ans[m-]);ans[m-]=;
}
return ;
}

HDU5909Tree Cutting的更多相关文章

  1. hdu5909-Tree Cutting(树形dp)

    偷偷抄bestcoser上面hnust_zhaozhixuan的代码 = = 因为题解看不懂阿 #include <cstdio> #include <cstring> typ ...

  2. hdu5909-Tree Cutting【FWT】

    正题 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5909 题目大意 给出\(n\)和\(m\)(\(m=2^k\)).再给出一个大小为\(n\)的树 ...

  3. [ACM_几何] Metal Cutting(POJ1514)半平面割与全排暴力切割方案

    Description In order to build a ship to travel to Eindhoven, The Netherlands, various sheet metal pa ...

  4. 贪心 Codeforces Round #300 A Cutting Banner

    题目传送门 /* 贪心水题:首先,最少的个数为n最大的一位数字mx,因为需要用1累加得到mx, 接下来mx次循环,若是0,输出0:若是1,输出1,s[j]--: 注意:之前的0的要忽略 */ #inc ...

  5. 水题 Codeforces Round #300 A Cutting Banner

    题目传送门 /* 水题:一开始看错题意,以为是任意切割,DFS来做:结果只是在中间切出一段来 判断是否余下的是 "CODEFORCES" :) */ #include <cs ...

  6. POJ 2311 Cutting Game(Nim博弈-sg函数/记忆化搜索)

    Cutting Game 题意: 有一张被分成 w*h 的格子的长方形纸张,两人轮流沿着格子的边界水平或垂直切割,将纸张分割成两部分.切割了n次之后就得到了n+1张纸,每次都可以选择切得的某一张纸再进 ...

  7. UVa 10003 (可用四边形不等式优化) Cutting Sticks

    题意: 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用. 分析: d(i, j)表示切割第i个切点到第j个切点这段所需的最小费用.则有d(i, j) = ...

  8. Cutting Sticks

    题意: l长的木棒,给出n个切割点,每切一次的费用为切得木棒的长度,完成切割的最小费用. 分析: 区间dp入门,区间dp的特点,一个大区间的解可以转换成小区间的解组合起来,每个切割点的标号代表边界. ...

  9. Hadoop之父Doug Cutting

    生活中,可能所有人都间接用过他的作品,他是Lucene.Nutch .Hadoop等项目的发起人.是他,把高深莫测的搜索技术形成产品,贡献给普罗大众:还是他,打造了目前在云计算和大数据领域里如日中天的 ...

随机推荐

  1. MySQL之数据导入导出

    日常开发中,经常会涉及到对于数据库中数据的导入与导出操作,格式也有很多: TXT,CSV,XLS,SQL等格式,所以,在此总结一下,省的总是百度查询. 一 导出 1) 常用的方式就是使用现成的工具例如 ...

  2. Python3练习题 022:用递归函数反转字符串

    方法一 str = input('请输入若干字符:')   def f(x):     if x == -1:         return ''     else:         return s ...

  3. vue router 根据不同的id切换链接界面不刷新

    我们一般使用vue的router时候会根据不同的id来切换界面,但是界面没有立刻刷新.下面我们讲下如何解决这个问题. html: <template> <div id="a ...

  4. C#设计模式之1:策略模式

    首先需要说明的是该系列的所有内容都是基于headfirst设计模式来描述的.因为我之前也看过不少关于设计模式的书,还是发现这本最好,因为这本书里面给出的例子是最贴切实际的.不说了,开始这个系列吧! 策 ...

  5. mybatis二级缓存详解

    1  二级缓存简介 二级缓存是在多个SqlSession在同一个Mapper文件中共享的缓存,它是Mapper级别的,其作用域是Mapper文件中的namespace,默认是不开启的.看如下图: 1. ...

  6. 小程序和H5互调

    小程序跳H5页面 https://blog.csdn.net/mytljp/article/details/81030687(copy) H5页面跳小程序 https://blog.csdn.net/ ...

  7. Windows 10 & change DNS

    Windows 10 & change DNS https://www.windowscentral.com/how-change-your-pcs-dns-settings-windows- ...

  8. CSS单元的位置和层次-div标签

    我们都知道,在网页上利用HTML定位文字和图象是一件“令人心痛”的事情.我们必须使用表格标签和隐式GIF图象,即使这样也不能保证定位的精确,因为浏览器和操作平台的不同会使显示的结果发生变化. 而CSS ...

  9. ERP系统的问题

    1.业务统计报表导出超时 2.库存统计相关接口查询容易导致慢查询,而且慢查询出现在主库上

  10. 在Linq to sql 和 Entity framework 中使用lambda表达式实现left join

    在Linq to sql 和 Entity framework 中使用lambda表达式实现left join 我们知道lambda表达式在Linq to sql 和 Entity framework ...