hdu5593--ZYB's Tree(树形dp)

问题描述

ZYB有一颗N个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数.

两个点(x,y)在树上的距离定义为两个点树上最短路径经过的边数,

为了节约读入和输出的时间,我们采用如下方式进行读入输出:

读入:读入两个数A,B,令fai??为节点i的父亲,fa?1??=0;fa?i??=(A∗i+B)%(i−1)+1,i∈[2,N] .

输出:输出时只需输出N个点的答案的xor和即可。

输入描述

第一行一个整数TT表示数据组数。

接下来每组数据:

 一行四个正整数N,K,A,B.

 最终数据中只有两组N≥100000。

1≤T≤5,5000001≤N≤500000,1≤K≤10,10000001≤A,B≤1000000

输出描述

T行每行一个整数表示答案.

输入样例

1
3 1 1 1

输出样例

3

re了好多好多次。注意数据范围A*i+B是会超int的!

距离一个点距离为k的值就用距离这个点距离为1的点更新。可能是该点的儿子,也可能是该点的父亲。

儿子节点直接算没有什么需要注意的地方。然后 与父亲结点距离为k-1的节点的数量减去该节点贡献的部分 就是该节点经过父亲结点符合要求结点的数量。

父亲结点有个坑。。。首先,需要先算父亲结点再算儿子节点,其次更新时要倒着更新。。。具体看代码吧。。。

#include <bits/stdc++.h>

using namespace std;

typedef unsigned int ut;
typedef long long ll;

const int N = 500005;
const int K = 12;

struct Edge {
    int to, next;
} edge[N];
int head[N];
int cnt_edge;
void add_edge(int u, int v)
{
    edge[cnt_edge].to = v;
    edge[cnt_edge].next = head[u];
    head[u] = cnt_edge++;
}

int dp[N][K];
int fa[N];

int n, k;

void dfs(int u)
{
    dp[u][0] = 1;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        dfs(v);
        for (int j = 1; j <= k; ++j)
        {
            dp[u][j] += dp[v][j - 1];
        }
    }
}

void solve(int u)
{
    if (u != 1)
    {
        for (int j = k; j >= 2; --j)//这里需要注意 更新的方向!
        {
            dp[u][j] += dp[ fa[u] ][j - 1] - dp[u][j - 2];
        }
        dp[u][1]++;
    }

    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        solve(v);
    }
}

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int a, b;

        scanf("%d%d%d%d", &n, &k, &a, &b);
        cnt_edge = 0;
        memset(dp, 0, sizeof dp);
        memset(head, -1, sizeof head);
        for (int i = 2; i <= n; ++i)
        {
            int f = ((ll)a * i + b) % (i - 1) + 1;
            add_edge(f, i);
            fa[i] = f;
        }
        dfs(1);
        solve(1);
        int ans = 0;
        for (int i = 1; i <= n; ++i)
        {
            int tmp = 0;
            for (int j = 0; j <= k; ++j)
            {
                tmp += dp[i][j];
            }
            ans ^= tmp;
        }
        printf("%d\n", ans);
    }
    return 0;
}

  

hdu5593--ZYB's Tree(树形dp)

时间: 2024-12-06 00:36:43

hdu5593--ZYB's Tree(树形dp)的相关文章

hdu5593/ZYB&#39;s Tree 树形dp

ZYB's Tree Memory Limit: 131072/131072 K (Java/Others) 问题描述 ZYBZYB有一颗NN个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数. 两个点(x,y)(x,y)在树上的距离定义为两个点树上最短路径经过的边数, 为了节约读入和输出的时间,我们采用如下方式进行读入输出: 读入:读入两个数A,BA,B,令fa_ifa?i??为节点ii的父亲,fa_1=0fa?1??=0;fa_i=(A*i+B)\%(i-1)+1fa

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m

[hdu5593 ZYB&#39;s Tree] 树上统计

题意:给1棵N(≤500,000)个节点的树,每条边边权为1,求距离每个点距离不超过K(K≤10)的点的个数的xor和. 思路:由于K很小,可以考虑把距离作为状态的一部分,然后研究父子之间状态的联系.令ans[i][j]表示与i的距离为j的点的个数,那么ans[i][j]由两部分构成,一部分来源于子树,一部分来源于父亲,那么令f[i][j]表示从子树来的答案,g[i][j]表示从父亲来的答案,son(i)表示i的儿子,fa(i)表示i的父亲,则有: ans[i][j] = f[i][j] + g

codeforces161D - Distance in Tree 树形dp

题意:给你一棵树,问你树中距离为k的有多少种情况. 解题思路:树形dp  维护每个节点(1-K)深度的情况, 解题代码: 1 // File Name: 161d.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月03日 星期日 19时20分10秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #incl

URAL_1018 Binary Apple Tree 树形DP+背包

这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过程中,有点难表示转移 后来看了下大神的做法才知道其实可以用背包来模拟 树枝的去留,其实真的是个背包诶,每个子树枝就相当于物品,他占用了多少树枝量,带来多少的收益,就是用背包嘛,于是用树形DP+背包就可以做了 #include <iostream> #include <cstdio> #

Codeforces 461B Appleman and Tree(树形dp)

题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每个节点的父亲节点,以及每个点的颜色(0表示白色,1表示黑色),切断这棵树的k条边,使得树变成k+1个联通分量,保证每个联通分量有且仅有1个黑色节点.问有多少种分割方法. 解题思路:树形dp,dp[i][0]和dp[i][1]分别表示子树一下的分割方法中,i节点所在联通块不存在黑节点和已经存在一个黑节点的方案数. #include <cstdio> #include <c

CF 461B Appleman and Tree 树形DP

Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other vertices are colored white. Consider a set consisting of k (0 ≤ k < n) edges of Appleman's tree. If Appleman deletes these edges from the tree, then

hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定义每条路径的值为经过的节点的不同颜色数.求所有路径的值和. 思路:看题解后,才想出来的.树形dp. 求所有路径的值和 = 路径条数*总颜色数(n*(n-1)*colors/2)-sigma(每种颜色没有经过的路径条数) 主要是求每种颜色没有经过的路径条数. 画一棵树,我直接用颜色值表示节点编号. 2

URAL 1018 Binary Apple Tree 树形DP 好题 经典

1018. Binary Apple Tree Time limit: 1.0 secondMemory limit: 64 MB Let's imagine how apple tree looks in binary computer world. You're right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enu

Codeforces 462D Appleman and Tree 树形dp

题目链接:点击打开链接 题意: 给定n个点的树, 0为根,下面n-1行表示每个点的父节点 最后一行n个数 表示每个点的颜色,0为白色,1为黑色. 把树分成若干个联通块使得每个联通块有且仅有一个黑点,问有多少种分法(结果mod1e9+7) 思路: 树形dp,每个点有2个状态,已经归属于某个黑点和未归属于某个黑点. #include <cstdio> #include <vector> #include <iostream> using namespace std; #de