HDU 5593 ZYB's Tree (树形DP)

ZYB's Tree

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 787    Accepted Submission(s): 265


 

Problem Description

ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no more than K for each node.
the distance between two nodes(x,y) is defined the number of edges on their shortest path in the tree.

To save the time of reading and printing,we use the following way:

For reading:we have two numbers A and B ,let fai be the father of node i ,fa1=0 ,fai=(A∗i+B)%(i−1)+1 for i∈[2,N] .

For printing:let ansi be the answer of node i ,you only need to print the xor sum of all ansi .

 

Input

In the first line there is the number of testcases T .

For each teatcase:

In the first line there are four numbers N ,K ,A ,B

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

 

Output

For T lines,each line print the ans.

Please open the stack by yourself.

N≥100000 are only for two tests finally.

 

Sample Input

 

1 3 1 1 1

扫描二维码关注公众号,回复: 2894562 查看本文章
 

Sample Output

 

3

 

Source

BestCoder Round #65

 

Recommend

hujie   |   We have carefully selected several similar problems for you:  6437 6436 6435 6434 6433 

#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
/*
题目大意:给定一棵树的生成计算方式,
对每个点,计算距离小于等于k的个数,
并且对每个点这样的权重相异或,得到的值就是答案。

对于每个点,很明显有两种方式,一种是往下走距离为k,
一种是往上走距离为k.
令dp[i][k][0]为i节点往下走距离为k的点数,
dp[i][k][1]为i节点往上走距离为k的点数,

首先预处理往下走的点数,
分析下往上走的状态:
dp[u][k][1]=dp[p][k-1][1]///继续往上走
+dp[p][k-1][0]///往兄弟子树走
-dp[u][k-2][0]///减去走过本身的路。

当然空间可以优化下,第二个dfs运算的顺序要倒过来即可。。

*/

const int  maxn =5e5+5;
const int mod=1e9+7;
///0代表朝下走
///dp[u][k][0]=sigma dp[v][k-1][0],
///dp[u][k][1]=dp[p][k-1][1]+dp[p][k-1][0]-dp[u][k-2][0]
///链式前向星
struct node{int nxt,u;};
int head[maxn],tot=0;
node edge[maxn<<1];
void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
void add(int x,int y)
{
    edge[tot]=node{head[x],y};
    head[x]=tot++;
}

ll dp[maxn][15][2];///dp数组
ll n,k,a,b;

void dfs1(int u,int pre)
{
    dp[u][0][0]=dp[u][0][1]=1;
    for(int i=head[u];~i;i=edge[i].nxt)
    {
        int v=edge[i].u;
        if(v==pre) continue;
        dfs1(v,u);
        for(int i=1;i<=k;i++)  dp[u][i][0]+=dp[v][i-1][0];
    }
}

void dfs2(int u,int pre)
{
    for(int i=head[u];~i;i=edge[i].nxt)
    {
        int v=edge[i].u;
        if(v==pre) continue;
        for(int i=k;i>=2;i--) dp[v][i][1]=dp[u][i-1][1]+dp[u][i-1][0]-dp[v][i-2][0];
        dp[v][1][1]=dp[u][0][1];
        dfs2(v,u);
    }
}


int main()
{

    int t;scanf("%d",&t);
    while(t--)
    {
         init();
        memset(dp,0,sizeof(dp));

        scanf("%lld%lld%lld%lld",&n,&k,&a,&b);
        for(int i=2;i<=n;i++)
        {
            ll tp=((ll)a*i+b)%(i-1)+1;
            add(tp,i);
            add(i,tp);
        }

        dfs1(1,-1);
        dfs2(1,-1);

        ll ans=0,tp=0;
        for(int i=1;i<=n;i++,tp=0)
        {
            for(int j=0;j<=k;j++)  tp=tp+dp[i][j][0]+dp[i][j][1];
            ans^=(tp-1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/82025313