题目大意

给定一颗树,每个点有点权,问对于每个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. #Leetcode# 989. Add to Array-Form of Integer

    https://leetcode.com/problems/add-to-array-form-of-integer/ For a non-negative integer X, the array- ...

  2. nodejs 中的一些方法

    fs.unlink(path, [callback(err)]) //删除文件操作. //path 文件路径 //callback 回调,传递一个异常参数err. ndoe中解决跨域问题 expres ...

  3. 弹性(flex)布局

    五大主流浏览器及其内核:谷歌浏览器:Google Chrome.内核是blink火狐浏览器:Mozilla Firefox.内核是Gecko:欧鹏浏览器:OPera.内核是blink苹果浏览器:Saf ...

  4. ORA-12541:TNS:无监听程序 解决办法

    昨天我在一台win7笔记本中安装了oracle11g,然后打算用另一个win10的笔记本使用plsql developer局域网内连接访问oracle数据库.但是遇到ORA-12541:TNS:无监听 ...

  5. Oracle调优总结

    Oracle调优总结(经典实践 重要) https://blog.csdn.net/dtjiawenwang88/article/details/74892245 https://www.cnblog ...

  6. python之路-字符串

    一.类型转换 a = 10 print(type(a)) # <class 'int'> d = str(a) # 把数字转换成str print(type(d)) # <class ...

  7. python设计模式第五天【单例模式】

    1. 定义 一个类只有一个实例,提供访问该实例的全局方法 2.应用场景 (1)多线程之间共享对象资源 (2)整个程序空间中的全局变量,共享资源 (3)大规模程序的节省创建对象的时间 3.代码实现(使用 ...

  8. python numpy笔记(重要)

    1.np.array 的shape (2,)与(2,1)含义 ndarray.shape:数组的维度.为一个表示数组在每个维度上大小的整数元组.例如二维数组中,表示数组的“行数”和“列数”. ndar ...

  9. 【python练习题】程序4

    # 题目:输入某年某月某日,判断这一天是这一年的第几天? import time year = input('输入年份: \n') month = input('输入月份: \n') day = in ...

  10. 洛谷 P1484 种树

    题目描述 cyrcyr今天在种树,他在一条直线上挖了n个坑.这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树.而且由于cyrcyr的树种不够,他至多会种k棵树 ...