树型dp hdu5593 ZYB's Tree

来源:互联网 发布:js高级程序设计最新 编辑:程序博客网 时间:2024/06/16 01:50

传送门:点击打开链接

题意:告诉你如何构造一颗树,然后询问有多少点对的距离小于等于K(K<=10)

思路:用csy的话来说,这就是个傻逼题,然而比赛的时候就是傻逼不会- -

设dp[u][k]表示当节点u作为子树的根节点时,在这个子树中有多少点对与u的距离<=k

那么ans[u]=dp[u][k]+sigma(dp[v][k-i]-dp[vlast][k-i-1]) 1<=i<=k,i表示向父节点走的距离,v表示距离u为i的父节点,vlast表示距离u为k-1的父节点。

其实就是说,如果选u作为一个点对的其中一个点后,另一个点要么出现在它作为根节点所在的子树中,那么这部分答案就是dp[u][k]

另外有可能就是在除了这个子树的其他位置上。那么我就去向上找父节点,以父节点作为拐弯点,求出dp[v][k-i]的个数,因为又包括了自己子树的一部分,再减去dp[vlast][k-i-1]就搞定了。

只有一个要注意的地方,就是生成树的那个函数中,A*i可能会爆int如果不用LL可能会RE,还有就是前面那个公式i=k的时候,要特判一下,因为此时k-i-1会是负数

#include<map>#include<set>#include<cmath>#include<ctime>#include<stack>#include<queue>#include<cstdio>#include<cctype>#include<string>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#include<functional>#define fuck(x) cout<<"["<<x<<"]"#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;const int MX = 5e5 + 5;struct Edge {    int v, nxt;} E[MX];int Head[MX], rear = 0;void edge_init() {    rear = 0;    memset(Head, -1, sizeof(Head));}void edge_add(int u, int v) {    E[rear].v = v;    E[rear].nxt = Head[u];    Head[u] = rear++;}int N, K, A, B;int f[MX], dp[MX][12];void DFS(int u) {    for(int i = 0; i <= K; i++) {        dp[u][i] = 1;    }    for(int j = Head[u]; ~j; j = E[j].nxt) {        int v = E[j].v; DFS(v);        for(int i = 1; i <= K; i++) {            dp[u][i] += dp[v][i - 1];        }    }}void init() {    f[1] = 0;    edge_init();    memset(dp, 0, sizeof(dp));    for(int i = 2; i <= N; i++) {        int pre = ((LL)A * i + B) % (i - 1) + 1;        edge_add(pre, i);        f[i] = pre;    }    DFS(1);}int solve() {    int ret = 0;    for(int u = 1; u <= N; u++) {        int last = u, now, ans = dp[u][K];        for(int i = 1; i <= K; i++) {            now = f[last];            if(!now) break;            if(K == i) ans += 1;            else ans += dp[now][K - i] - dp[last][K - i - 1];            last = now;        }        ret ^= ans;    }    return ret;}int main() {    int T; //FIN;    scanf("%d", &T);    while(T--) {        scanf("%d%d%d%d", &N, &K, &A, &B);        init();        printf("%d\n", solve());    }    return 0;}


0 0
原创粉丝点击