zoukankan      html  css  js  c++  java
  • BZOJ5293:[BJOI2018]求和(LCA,差分)

    Description

    master 对树上的求和非常感兴趣。他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k
     次方和,而且每次的k 可能是不同的。此处节点深度的定义是这个节点到根的路径上的边数。他把这个问题交给
    了pupil,但pupil 并不会这么复杂的操作,你能帮他解决吗?

    Input

    第一行包含一个正整数n ,表示树的节点数。
    之后n-1 行每行两个空格隔开的正整数i,j ,表示树上的一条连接点i 和点j 的边。
    之后一行一个正整数m ,表示询问的数量。
    之后每行三个空格隔开的正整数i,j,k ,表示询问从点i 到点j 的路径上所有节点深度的k 次方和。
    由于这个结果可能非常大,输出其对998244353 取模的结果。
    树的节点从1 开始标号,其中1 号节点为树的根。

    Output

    对于每组数据输出一行一个正整数表示取模后的结果。
    1≤n,m≤300000,1≤k≤50

    Sample Input

    5
    1 2
    1 3
    2 4
    2 5
    2
    1 4 5
    5 4 45

    Sample Output

    33
    503245989
    说明
    样例解释
    以下用d(i) 表示第i 个节点的深度。
    对于样例中的树,有d(1)=0,d(2)=1,d(3)=1,d(4)=2,d(5)=2。
    因此第一个询问答案为(2^5 + 1^5 + 0^5) mod 998244353 = 33
    第二个询问答案为(2^45 + 1^45 + 2^45) mod 998244353 = 503245989。

    Solution

    最近好没状态,感觉要钦定退役了
    对于这个题,如果不考虑k次方的话就是裸的树上差分
    然后发现k非常小,就可以把所有k次方的情况全部记录下来
    全WA到取模和longlong上了……

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define MOD (998244353)
     5 #define N (300000+100)
     6 using namespace std;
     7 
     8 struct node
     9 {
    10     int to,next;
    11 }edge[N*2];
    12 int Father[N],a[N],Depth[N],f[N][21],Sum[N][52],Pow[N][52];
    13 int head[N],num_edge,n,m,x,y,k;
    14 
    15 void add(int u,int v)
    16 {
    17     edge[++num_edge].to=v;
    18     edge[num_edge].next=head[u];
    19     head[u]=num_edge;
    20 }
    21 
    22 void Build(int x)
    23 {
    24     Depth[x]=Depth[Father[x]]+1;
    25     Sum[x][0]=1; Pow[x][0]=1;
    26     for (int i=1; i<=50; ++i) 
    27     {
    28         Pow[x][i]=((long long)Pow[x][i-1]*(long long)Depth[x])%MOD;
    29         Sum[x][i]=(Sum[Father[x]][i]+Pow[x][i])%MOD;
    30     }
    31     
    32     for (int i=head[x]; i; i=edge[i].next)
    33         if (edge[i].to!=Father[x])
    34         {
    35             Father[edge[i].to]=x;
    36             f[edge[i].to][0]=x;
    37             Build(edge[i].to);
    38         }
    39 }
    40 
    41 int LCA(int x,int y)
    42 {
    43     int ans=0;
    44     if (Depth[x]<Depth[y]) swap(x,y);
    45     for (int i=19; i>=0; --i)
    46         if (Depth[f[x][i]]>=Depth[y])
    47             x=f[x][i];
    48     if (x==y) return x;
    49     for (int i=19; i>=0; --i)
    50         if (f[x][i]!=f[y][i])
    51             x=f[x][i],y=f[y][i];
    52     return Father[x];
    53 }
    54 
    55 int main()
    56 {
    57     scanf("%d",&n);
    58     for (int i=1; i<=n-1; ++i)
    59     {
    60         scanf("%d%d",&x,&y);
    61         add(x,y); add(y,x);
    62     }
    63     Depth[0]=-1;
    64     Build(1);
    65     for (int i=1; i<=19; ++i)
    66         for (int j=1;j<=n;++j)
    67             f[j][i]=f[f[j][i-1]][i-1];
    68     scanf("%d",&m);
    69     for (int i=1; i<=m; ++i)
    70     {
    71         scanf("%d%d%d",&x,&y,&k);
    72         int lca=LCA(x,y);
    73         printf("%d
    ",((Sum[x][k]+Sum[y][k]-Sum[Father[lca]][k]-Sum[lca][k])%MOD+MOD)%MOD);
    74     }
    75 }
  • 相关阅读:
    HDU 2196 Computer
    HDU 1520 Anniversary party
    POJ 1217 FOUR QUARTERS
    POJ 2184 Cow Exhibition
    HDU 2639 Bone Collector II
    POJ 3181 Dollar Dayz
    POJ 1787 Charlie's Change
    POJ 2063 Investment
    HDU 1114 Piggy-Bank
    Lca hdu 2874 Connections between cities
  • 原文地址:https://www.cnblogs.com/refun/p/8932673.html
Copyright © 2011-2022 走看看