bjoi 2018 求和 唯一一道可能切的题一个数组还没开long long就成0分了
题目大意:
一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k次方和,而且每次的k可能是不同的
此处节点深度的定义是这个节点到根的路径上的边数
思路:
考试的时候随便写了个树剖
剖下来之后搞五十个次方的前缀和
然后一个数组乘起来没开long long
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #define ll long long 10 #define MAXN 300100 11 #define inf 2139062143 12 #define MOD 998244353 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 19 return x*f; 20 } 21 int n,m,hsh[MAXN],HSH[MAXN],bl[MAXN],sz[MAXN],dep[MAXN],fa[MAXN]; 22 int nxt[MAXN<<1],fst[MAXN],to[MAXN<<1],cnt; 23 ll sum[51][MAXN],val[MAXN],res; 24 void add(int u,int v){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 25 void dfs(int x) 26 { 27 sz[x]=val[x]=1; 28 for(int i=fst[x];i;i=nxt[i]) 29 { 30 if(to[i]==fa[x]) continue; 31 dep[to[i]]=dep[x]+1,fa[to[i]]=x; 32 dfs(to[i]);sz[x]+=sz[to[i]]; 33 } 34 } 35 void DFS(int x,int anc) 36 { 37 int hvs=0;hsh[x]=++cnt,HSH[cnt]=x,bl[x]=anc; 38 for(int i=fst[x];i;i=nxt[i]) 39 if(to[i]!=fa[x]&&sz[to[i]]>sz[hvs]) hvs=to[i]; 40 if(!hvs) return ; 41 DFS(hvs,anc); 42 for(int i=fst[x];i;i=nxt[i]) 43 if(to[i]!=fa[x]&&to[i]!=hvs) DFS(to[i],to[i]); 44 } 45 int main() 46 { 47 n=read();int a,b,c; 48 for(int i=1;i<n;i++) {a=read(),b=read();add(a,b);add(b,a);} 49 dfs(1);cnt=0; 50 DFS(1,1); 51 for(int i=1;i<=50;i++) 52 for(int j=1;j<=n;j++) (val[j]*=dep[HSH[j]])%=MOD,sum[i][j]=(sum[i][j-1]+val[j])%MOD; 53 m=read(); 54 while(m--) 55 { 56 a=read(),b=read(),c=read(),res=0; 57 while(bl[a]!=bl[b]) 58 { 59 if(dep[bl[a]]<dep[bl[b]]) swap(a,b); 60 (res+=sum[c][hsh[a]]-sum[c][hsh[bl[a]]-1]+MOD)%=MOD; 61 a=fa[bl[a]]; 62 } 63 if(dep[a]>dep[b]) swap(a,b); 64 (res+=sum[c][hsh[b]]-sum[c][hsh[a]-1]+MOD)%=MOD; 65 printf("%lld\n",res); 66 } 67 }
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8856720.html
时间: 2024-10-07 21:32:51