HDU5909Tree Cutting
题目大意
给定一颗树,每个点有点权,问对于每个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的更多相关文章
- hdu5909-Tree Cutting(树形dp)
偷偷抄bestcoser上面hnust_zhaozhixuan的代码 = = 因为题解看不懂阿 #include <cstdio> #include <cstring> typ ...
- hdu5909-Tree Cutting【FWT】
正题 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5909 题目大意 给出\(n\)和\(m\)(\(m=2^k\)).再给出一个大小为\(n\)的树 ...
- [ACM_几何] Metal Cutting(POJ1514)半平面割与全排暴力切割方案
Description In order to build a ship to travel to Eindhoven, The Netherlands, various sheet metal pa ...
- 贪心 Codeforces Round #300 A Cutting Banner
题目传送门 /* 贪心水题:首先,最少的个数为n最大的一位数字mx,因为需要用1累加得到mx, 接下来mx次循环,若是0,输出0:若是1,输出1,s[j]--: 注意:之前的0的要忽略 */ #inc ...
- 水题 Codeforces Round #300 A Cutting Banner
题目传送门 /* 水题:一开始看错题意,以为是任意切割,DFS来做:结果只是在中间切出一段来 判断是否余下的是 "CODEFORCES" :) */ #include <cs ...
- POJ 2311 Cutting Game(Nim博弈-sg函数/记忆化搜索)
Cutting Game 题意: 有一张被分成 w*h 的格子的长方形纸张,两人轮流沿着格子的边界水平或垂直切割,将纸张分割成两部分.切割了n次之后就得到了n+1张纸,每次都可以选择切得的某一张纸再进 ...
- UVa 10003 (可用四边形不等式优化) Cutting Sticks
题意: 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用. 分析: d(i, j)表示切割第i个切点到第j个切点这段所需的最小费用.则有d(i, j) = ...
- Cutting Sticks
题意: l长的木棒,给出n个切割点,每切一次的费用为切得木棒的长度,完成切割的最小费用. 分析: 区间dp入门,区间dp的特点,一个大区间的解可以转换成小区间的解组合起来,每个切割点的标号代表边界. ...
- Hadoop之父Doug Cutting
生活中,可能所有人都间接用过他的作品,他是Lucene.Nutch .Hadoop等项目的发起人.是他,把高深莫测的搜索技术形成产品,贡献给普罗大众:还是他,打造了目前在云计算和大数据领域里如日中天的 ...
随机推荐
- java代理:静态代理和动态代理
一.Java中有一个设计模式是代理模式 代理模式是常用的Java设计模式,特征是代理类与委托类有相同的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类 ...
- [转帖]NUMA架构的CPU -- 你真的用好了么?
NUMA架构的CPU -- 你真的用好了么? 本文从NUMA的介绍引出常见的NUMA使用中的陷阱,继而讨论对于NUMA系统的优化方法和一些值得关注的方向. 文章欢迎转载,但转载时请保留本段文字,并置于 ...
- [转帖]Linux下fork函数及pthread函数的总结
Linux下fork函数及pthread函数的总结 https://blog.csdn.net/wangdd_199326/article/details/76180514 fork Linux多进程 ...
- JSON Support in PostgreSQL and Entity Framework
JSON 和JSONB的区别(What's difference between JSON and JSONB data type in PosgresSQL?) When should be use ...
- ArrayList的扩容机制
一.ArrayList的扩容机制 1.扩容的计算方式是向右位移,即:newSize = this.size + (this.size>>1).向右位移,只有在当前值为偶数时,才是除以2:奇 ...
- 压测工具使用(vegeta)
一.压测工具vegeta 1.介绍 Vegeta 是一个用 Go 语言编写的多功能的 HTTP 负载测试工具,它提供了命令行工具和一个开发库. 官方地址:https://github.com/tsen ...
- mysql对身份证号码进行脱敏处理
select * from test 格式:INSERT(str,pos,len,newstr) 解释: str:查询的例 pos:起始位置 len:从起始位置开始被后面newstr替换的长度 new ...
- 记一次生产mysql数据误操作恢复过程
提示:建议每次对数据库进行修改时都做下备份 注意:以下Mysql开启的是row格式的binlog日志,确定到误操作具体时间可能有些麻烦,默认的格式就能很快找出来.这里开启row的原因是还有一种更快的方 ...
- UML符号
转抄, 语言简练. 挺好. ------------------- ------------------- ------------------- ------------------- -- ...
- 实现中英文混合string的逆向输出
#include <iostream> using namespace std; // 输入一个字符串(包括英文和中文),将其反序输出, 如: // hello 今天真热 ---> ...