题:https://nanti.jisuanke.com/t/41403

题意:求任意俩点之间距离之和模3后的三个结果的总数(原距离之和)

第一种做法:

树形dp

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
typedef long long ll;
const int M=1e4+;
const int mod=1e9+;
struct node{
int v;
ll w;
};
ll C[M][],S[M][],ans[M];
//C[i][j]:表示以i为根,然后路径消耗取模后为j的路径数
//S[i][j]:表示以i为根,路径消耗取模后为j的路径总消耗
vector<node>e[M];;
void dfs(int u,int f,ll pre){
C[u][]=C[u][]=C[u][]=;
S[u][]=S[u][]=S[u][]=;
int len=e[u].size();
for(int i=;i<e[u].size();i++){
int v=e[u][i].v;
if(v==f)
continue;
dfs(v,u,e[u][i].w);
//算跨越跟节点的贡献
for(int p=;p<;p++){
for(int j=;j<;j++)
for(int k=;k<;k++)
if(p==(j+k)%)
ans[p]=(ans[p]+S[u][j]*C[v][k]%mod+C[u][j]*S[v][k]%mod)%mod;
}
for(int j=;j<;j++){
C[u][j]=(C[u][j]+C[v][j])%mod;
S[u][j]=(S[u][j]+S[v][j])%mod;
} } for(int i=;i<;i++)//算以u为跟对答案的贡献,就直接算u的每一个子树的贡献 ans[i]=(ans[i]+S[u][i])%mod;
ll c[],s[];
memset(c,0ll,sizeof(c));
memset(s,0ll,sizeof(s));
for(int i=;i<;i++){
int t=(i-pre%+)%;
c[i]=(c[i]+C[u][t])%mod;
s[i]=(s[i]+(S[u][t]+C[u][t]*pre%mod)%mod)%mod;
}
if(f!=)
c[pre%]=(c[pre%]+1ll)%mod,s[pre%]=(s[pre%]+pre)%mod;
for(int i=;i<;i++)
C[u][i]=c[i],S[u][i]=s[i];
}
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++)
e[i].clear();
memset(S,,sizeof(S));
memset(C,,sizeof(C));
for(int i=;i<n;i++){
int u,v;
ll w;
for(int i=;i<;i++)
ans[i]=0ll;
scanf("%d%d%lld",&u,&v,&w);
u++,v++;
e[u].pb(node{v,w});
e[v].pb(node{u,w});
}
dfs(,,);
printf("%lld %lld %lld\n",ans[]*2ll%mod,ans[]*2ll%mod,ans[]*2ll%mod); }
return ;;
}

第二种做法:

点分治

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=2e4+;
const ll mod=1e9+;
struct node{
int v,nextt;
ll w;
}e[M<<];
ll sum[],disnum[],dissum[];
int head[M],vis[M],sz[M],maxv[M],tot,n,maxx,root;
void addedge(int u,int v,ll w){
e[tot].v=v;
e[tot].nextt=head[u];
e[tot].w=w;
head[u]=tot++;
}
void dfssz(int u,int f){
maxv[u]=;
sz[u]=;
for(int i=head[u];~i;i=e[i].nextt){
int v=e[i].v;
if(v==f||vis[v])
continue;
dfssz(v,u);
sz[u]+=sz[v];
maxv[u]=max(maxv[u],sz[v]);
}
}
void dfsroot(int r,int u,int f){
maxv[u]=max(maxv[u],sz[r]-sz[u]);
if(maxx>maxv[u]){
maxx=maxv[u];
root=u;
}
for(int i=head[u];~i;i=e[i].nextt){
int v=e[i].v;
if(v==f||vis[v])
continue;
dfsroot(r,v,u);
}
}
void dfsdis(int u,int f,ll d){
// if(f!=-1&&d!=0)
disnum[d%]++;
disnum[d%]%=mod;
dissum[d%]+=d;
dissum[d%]%=mod;
for(int i=head[u];~i;i=e[i].nextt){
int v=e[i].v;
if(vis[v]||v==f)
continue;
dfsdis(v,u,(d+e[i].w)%mod);
}
}
void cal(int u,ll d,int flag){
for(int i=;i<;i++)
dissum[i]=disnum[i]=; dfsdis(u,-,d);
for(int i=;i<;i++)
for(int j=;j<;j++){
int t=(i+j)%;
sum[t]=(sum[t]+flag*((disnum[i]*dissum[j]%mod+disnum[j]*dissum[i]%mod)%mod)%mod+mod)%mod;
}
}
void solve(int u){
maxx=n;
dfssz(u,-);
dfsroot(u,u,-);
cal(root,0ll,);//+
vis[root]=;
for(int i=head[root];~i;i=e[i].nextt){
int v=e[i].v;
if(vis[v])
continue;
cal(v,e[i].w,-);
solve(v);
}
}
int main(){
while(~scanf("%d",&n)){
sum[]=sum[]=sum[]=;
tot=;
for(int i=;i<=n;i++)
head[i]=-,vis[i]=;;
for(int i=;i<n;i++){
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
u++,v++;
addedge(u,v,w);
addedge(v,u,w);
}
solve();
printf("%lld %lld %lld\n",sum[],sum[],sum[]);
}
return ;
}

D. Fish eating fruit的更多相关文章

  1. Fish eating fruit 沈阳网络赛(树形dp)

    Fish eating fruit \[ Time Limit: 1000 ms \quad Memory Limit: 262144 kB \] 题意 大体的题意就是给出一棵树,求每一对点之间的距离 ...

  2. 2019icpc沈阳网络赛 D Fish eating fruit 树形dp

    题意 分别算一个树中所有简单路径长度模3为0,1,2的距离和乘2. 分析 记录两个数组, \(dp[i][k]\)为距i模3为k的子节点到i的距离和 \(f[i][k]\)为距i模3为k的子节点的个数 ...

  3. 2019 沈阳网络赛 Fish eating fruit

    这题看了三个月,终于过了,第一次看的时候没学树形DP,想用点分治但是不会 后来学了二次扫描,就有点想法了.... 这东西也真就玄学了吧... #include<iostream> #inc ...

  4. The Preliminary Contest for ICPC Asia Shenyang 2019 D. Fish eating fruit(树形dp)

    题意:求一棵树上所有路径和模3分别为0 1 2 的权值的和 思路:树形dp 增加一个记录儿子节点满足条件的个数的数组 不要放在一起dp不然答案跟新会有问题 #include <bits/stdc ...

  5. 2019 沈阳网络赛 D Fish eating fruit ( 树形DP)

    题目传送门 题意:求一颗树中所有点对(a,b)的路径长度,路径长度按照模3之后的值进行分类,最后分别求每一类的和 分析:树形DP \(dp[i][j]\) 表示以 i 为根的子树中,所有子节点到 i ...

  6. 2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)

    链接: https://nanti.jisuanke.com/t/41403 题意: State Z is a underwater kingdom of the Atlantic Ocean. Th ...

  7. The Preliminary Contest for ICPC Asia Shenyang 2019

    传送门 B. Dudu's maze 题意: 是什么鬼东西???我读题可以读半小时QAQ 给出一张无向图,一个人在里面收集糖果,每个点都有一个糖果,特殊点除外.当他第一次进入特殊点时,会随机往一条边走 ...

  8. SpringRMI远程方法调用

    Spring为各种远程访问技术的集成提供了工具类. 该小段引用自 http://www.open-open.com/lib/view/open1408957290478.html Spring远程支持 ...

  9. SpringRMI远程方法调用【原】

    Spring为各种远程访问技术的集成提供了工具类. 该小段引用自 http://www.open-open.com/lib/view/open1408957290478.html Spring远程支持 ...

随机推荐

  1. AJAX(阿贾克斯)的简单应用

    1.ajax 对象的属性说明(常用的) (1)open(method,url,boolean);创建请求,method :填请求类型(get post),url :请求的地址, boolean:tru ...

  2. redis官网下载自动安装脚本

    注释:使用方法为 # ./redis.sh  version           ----version为官网版本号 #!/bin/bashversion=$1serverurl='download. ...

  3. 设计模式讲解5:FlyWeight模式源码

    声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635 FlyWeight模式即享元模式.很多文本编辑器中都使用了FlyWeight模式.FlyWeight单词含 ...

  4. sqlmap简单流程使用

    -u “(url)” 1.判断可注入的参数 2.判断可以用那种SQL注入技术来注入 3.识别出哪种数据库 4.根据用户选择,读取哪些数据 sqlmap支持五种不同的注入模式: 1.基于布尔的盲注,即可 ...

  5. 解决 springweb Filter 读取request body miss body

    package com.lb.demo.listener; import java.io.BufferedReader; import java.io.ByteArrayInputStream; im ...

  6. CodeForces-1100C NN and the Optical Illusion 简单数学

    题目链接:https://vjudge.net/problem/CodeForces-1100C 题意: 题目给出外部圆的数目n和内部圆的半径r,要求求出外部圆的半径以满足图片要求. 显然这是一道数学 ...

  7. not in 优化 NOT EXISTS替代

    优化前 SELECT id, loan_id, NAME FROM xw_baoxian_interchange WHERE , , ) , ) AND loan_id NOT IN ( SELECT ...

  8. leetcode中的sql

    1 组合两张表 组合两张表, 题目很简单, 主要考察JOIN语法的使用.唯一需要注意的一点, 是题目中的这句话, "无论 person 是否有地址信息".说明即使Person表, ...

  9. 微信小程序2048开发进度(一)

    父亲是个体劳动者,他的兴趣就是下象棋,针对平时兴趣,我想做一款自己的2048小游戏,在慕课网观看了2048小游戏的讲解,以及关于开发小游戏的理论知识,对开发一款小游戏有了基本的认识.

  10. Graph & Trees3 - 二分图

    \[二分图略解\] \[By\;TYQ\] 二分图定义: \(f(i,L) = [a \in L\;\text{&}\;\forall b \in a.to \;\text{,}\; b \n ...