【BestCoder Round 65D】【树形DP 容斥思想】ZYB's Tree 求距离每个节点距离不超过k的节点数
2015-12-08 09:11
696 查看
ZYB's Tree
Accepts: 77
Submissions: 513
Time Limit: 3000/1500 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
ZYBZYB有一颗NN个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数. 两个点(x,y)(x,y)在树上的距离定义为两个点树上最短路径经过的边数, 为了节约读入和输出的时间,我们采用如下方式进行读入输出: 读入:读入两个数A,BA,B,令fa_ifai为节点ii的父亲,fa_1=0fa1=0;fa_i=(A*i+B)\%(i-1)+1fai=(A∗i+B)%(i−1)+1 i \in [2,N]i∈[2,N] . 输出:输出时只需输出NN个点的答案的xorxor和即可。
输入描述
第一行一个整数TT表示数据组数。 接下来每组数据: 一行四个正整数N,K,A,BN,K,A,B. 最终数据中只有两组N \geq 100000N≥100000。 1 \leq T \leq 51≤T≤5,1 \leq N \leq 5000001≤N≤500000,1 \leq K \leq 101≤K≤10,1 \leq A,B \leq 10000001≤A,B≤1000000
输出描述
TT行每行一个整数表示答案.
输入样例
1 3 1 1 1
输出样例
3
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=5e5+10,M=1e6+10,Z=1e9+7,ms63=1061109567;
int casenum,casei;
int n,K,A,B;
int first
,id;
int w[M],nxt[M];
bool e
;
int f
[12],ans;
inline void ins(int x,int y)
{
++id;
w[id]=y;
nxt[id]=first[x];
first[x]=id;
}
void dfs(int x)
{
e[x]=1;
f[x][0]=1;for(int i=1;i<=K;++i)f[x][i]=0;
for(int z=first[x];z;z=nxt[z])
{
int y=w[z];
if(e[y])continue;
dfs(y);
for(int i=1;i<=K;++i)f[x][i]+=f[y][i-1];
}
}
void dp(int x)
{
e[x]=0;
for(int z=first[x];z;z=nxt[z])
{
int y=w[z];
if(!e[y])continue;
for(int i=K;i>=2;--i)f[y][i]+=f[x][i-1]-f[y][i-2];++f[y][1];
dp(y);
}
int tmp=0;
for(int i=0;i<=K;++i)tmp+=f[x][i];
ans^=tmp;
}
int main()
{
scanf("%d",&casenum);
for(casei=1;casei<=casenum;++casei)
{
scanf("%d%d%d%d",&n,&K,&A,&B);
memset(first,0,n+2<<2);id=0;
for(int i=2;i<=n;++i)
{
int j=((LL)A*i+B)%(i-1)+1;
ins(i,j);ins(j,i);
}
ans=0;
dfs(1);
dp(1);
printf("%d\n",ans);
}
return 0;
}
/*
【trick&&吐槽】
1,csy向我透露说,这次BC有题可以暴力过!
于是我就写了个暴力,然后TLE……
果然还是要自己思考,不能再被骗了2333
2,A和B都是1e6范围的数,所以乘法可能会爆int,一定要注意啊>_<
3,这么水的题比赛时候竟然没认真想过,我好蠢!
【题意】
给你一棵树,树上有n(5e5)个节点,让你求出,对于所有点而言的,距离不超过K(1<=K<=10)的节点数。
然后输出这所有节点数的异或和。
【类型】
树形DP
【分析】
首先,这是树结构。
然后,我们尝试简化问题。
如果求的,不是对于一个节点,所有距离在[1,K]的节点数,而是限制在子树内的距离在[1,K]的节点数。
那么,这道题,我们直接一个dfs就可以搞定。
就是从叶子节点开始,距离这个节点距离为[1,K]的节点数。
然后f[x][i]=∑f[son][i-1],i∈[1,K]
f[x][0]=1
然而,我们还要求与非子树内的节点,怎么办呢?
我们做完之前的预处理之后,只需要从父节点寻求转移即可。
我们假设,我们已经知道了距离父节点x距离为0~K的所有点的点数。我们现在要向子节点y转移。
显然,f[y][i]+=f[x][i-1]-f[y][i-2],2<=i<=K。
++f[y][1];
意思是,距离父节点x为i-1的节点,转移到节点y的时候,距离就变成了i。
然而, 并非所有的节点都能做转移。y子树内的,距离为y为i-2的节点,距离父节点的距离也是i-1,但是距离y的距离并非为i。
所以我们把这些节点剔除。
一个转移从子节点转移而来,另外一个转移从父节点转移而来。
同时DP的时候要注意使用合理的拓扑序,就可以顺利AC这道题啦。啦啦啦啦~
【时间复杂度&&优化】
O(nk)
【数据】
调试代码——
for(int i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);
ins(y,x);
}
input
14 5 1 1
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
9 10
1 11
11 12
12 13
13 14
output
8
*/
相关文章推荐
- [HAOI2010][DP]最长公共子序列
- hdu 5212(容斥)
- hdu 5468 Puzzled Elena 预处理+深搜+容斥
- SGU 537 Divisibility
- 【Codeforces Round 324 (Div 2)B】【容斥】Kolya and Tanya 环上n个3元组至少有一组和不为6
- 【HDU5565 BestCoder Round 62 (div1)C】【STL or 二分答案 or 计数排序】Clarke and baton n个人减肥m次求最后异或值
- 【HDU5564 BestCoder Round 62 (div1)B】【DP转矩阵快速幂】Clarke and digits 长度在[l,r]范围内7倍数数个数要求相邻两位不为K
- 【HDU5544 2015CCPC 南阳国赛E】【树上dfs找本质不同环 高斯消元 时间戳优化】Ba Gua Zhen 连通图上最大异或环
- 【HDU5222 2015赛码冠军杯I】【并查集找双连通 + tarjan求强连通】Exploration 双向边只能走一边是否图上存在环
- 【HDU5188 BestCoder Round 33C】【贪心排序+DP】zhx and contest 考试不被怀疑作弊条件下达到至少m分的最少时间
- 【HDU4560 2013西山居复赛D】【二分答案+网络流拆点】我是歌手 安排演唱会_每人歌不同_每场歌不同_人歌匹配一次
- 【HDU5411 2015 Multi-University Training Contest 10F】【矩阵快速幂 加一行构造法】CRB and Puzzle 矩阵的1次方到n次方的数值和
- 【HDU5570 BestCoder Round 63 (div1)C】【期望DP 公式化简】balls n种求m种颜色,同颜色球数为x贡献为x方 求期望
- 【HDU5569 BestCoder Round 63 (div1)B】【DP】matrix 向右走向下走最大乘积和
- 【HDU5568 BestCoder Round 63 (div1)A】【DP java高精度】sequence2 长度恰好为m的LIS数
- 【HDU5579 2015上海赛区G】【超级大讨论】Game of Arrays a[]+b[]+c[]有些位置可以减一,状态是否可能达成
- 【HDU5583 2015上海赛区L】【找规律 正难则反】LCM Walk 目标状态(x,y)哪些点走公倍数能走到它
- 【HDU5573 2015上海赛区B】【构造 二进制思想】Binary Tree 二叉树上走m层加减数使得最后权值恰为n
- 【HDU5583 2015上海赛区K】【暴力合并】Kingdom of Black and White 连续01串权值贡献为len^2最多改变一次最大权值
- 【HDU5578 2015上海赛区F】【水题】Friendship of Frog 最近的两个相同字符的距离是多少