[题目链接]

https://codeforces.com/contest/715/problem/C

[算法]

考虑点分治

一条路径(x , y)合法当且仅当 : d(x) * 10 ^ dep(x) + d(y) = 0(mod m) , 其中d(u)表示u到分治重心路径上数字拼接起来所形成的数

统计答案时 , 我们只需维护一个map , 维护10 ^ -dep(u) * d(u) (mod m)

然后计算每个点的贡献即可

时间复杂度 : O(NlogN ^ 2)

[代码]

#include<bits/stdc++.h>
using namespace std;
#define N 100010
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull; struct edge
{
int to , w , nxt;
} e[N << ]; int n , m , tot , len , root;
ll ans;
int pw[N] , head[N] , size[N] , weight[N] , D[N] , depth[N];
bool visited[N];
map<int , int> mp; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
inline void addedge(int u , int v , int w)
{
++tot;
e[tot] = (edge){v , w , head[u]};
head[u] = tot;
}
inline void getroot(int u , int par , int total)
{
size[u] = ;
weight[u] = ;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == par || visited[v]) continue;
getroot(v , u , total);
size[u] += size[v];
chkmax(weight[u] , size[v]);
}
chkmax(weight[u] , total - size[u]);
if (weight[u] < weight[root]) root = u;
}
inline void exgcd(int a , int b , int &x , int &y)
{
if (b == )
{
x = ;
y = ;
} else
{
exgcd(b , a % b , y , x);
y -= a / b * x;
}
}
inline int inv(int a)
{
int x , y;
exgcd(a , m , x , y);
return (x % m + m) % m;
}
inline void dfs(int u , int par , int d1 , int d2)
{
if (depth[u] > ) ++mp[(1ll * d2 % m * inv(pw[depth[u]] % m)) % m];
D[++len] = d1;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to , w = e[i].w;
if (v == par || visited[v]) continue;
depth[v] = depth[u] + ;
dfs(v , u , (1ll * w * pw[depth[v] - ] % m + d1) % m , (10ll * d2 % m + w) % m);
}
}
inline ll calc(int u , int d)
{
mp.clear();
len = ;
if (!d) dfs(u , - , , );
else dfs(u , - , d % m , d % m);
ll res = ;
for (int i = ; i <= len; ++i)
{
int goal = ((m - D[i]) % m + m) % m;
res += (ll)mp[goal];
if (!d && !D[i]) ++res;
}
return res;
}
inline void work(int u)
{
visited[u] = true;
depth[u] = ;
ans += calc(u , );
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to , w = e[i].w;
if (visited[v]) continue;
depth[v] = ;
ans -= calc(v , w);
}
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (visited[v]) continue;
root = ;
getroot(v , u , size[v]);
work(root);
}
} int main()
{ read(n); read(m);
pw[] = ;
for (int i = ; i <= n; ++i) pw[i] = 1ll * pw[i - ] * % m;
for (int i = ; i < n; ++i)
{
int u , v , w;
read(u); read(v); read(w);
++u; ++v;
addedge(u , v , w);
addedge(v , u , w);
}
weight[] = n;
root = ;
getroot( , , n);
work(root);
ans -= n;
printf("%I64d\n" , ans); return ; }

[Codeforces 715C] Digit Tree的更多相关文章

  1. 【Codeforces 715C】Digit Tree(点分治)

    Description 程序员 ZS 有一棵树,它可以表示为 \(n\) 个顶点的无向连通图,顶点编号从 \(0\) 到 \(n-1\),它们之间有 \(n-1\) 条边.每条边上都有一个非零的数字. ...

  2. Codeforces 716 E Digit Tree

    E. Digit Tree time limit per test 3 seconds memory limit per test 256 megabytes input standard input ...

  3. 【题解】Digit Tree

    [题解]Digit Tree CodeForces - 716E 呵呵以为是数据结构题然后是淀粉质还行... 题目就是给你一颗有边权的树,问你有多少路径,把路径上的数字顺次写出来,是\(m\)的倍数. ...

  4. 【Codeforces715C&716E】Digit Tree 数学 + 点分治

    C. Digit Tree time limit per test:3 seconds memory limit per test:256 megabytes input:standard input ...

  5. Problem - D - Codeforces Fix a Tree

    Problem - D - Codeforces  Fix a Tree 看完第一名的代码,顿然醒悟... 我可以把所有单独的点全部当成线,那么只有线和环. 如果全是线的话,直接线的条数-1,便是操作 ...

  6. Codeforces 765 E. Tree Folding

    题目链接:http://codeforces.com/problemset/problem/765/E $DFS子$树进行$DP$ 大概分以下几种情况: 1.为叶子,直接返回. 2.长度不同的路径长度 ...

  7. codeforces 570 D. Tree Requests 树状数组+dfs搜索序

    链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds mem ...

  8. CodeForces 383C Propagating tree

    Propagating tree Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces ...

  9. 【19.77%】【codeforces 570D】Tree Requests

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

随机推荐

  1. layer的alert、prompt等操作如何响应键盘的回车和ESC操作

    layer.prompt({title: '请输入数据', formType: 1, //隐藏用户输入内容 // 这个是确定按钮的事件 "success":function(){ ...

  2. 10.【nuxt起步】-引用mintui

    这时候我们完成了list.vue,但是怎么返回index.vue,这时候需要这个头部返回 1.我们使用现成的minu-ui,eleme的开源移动端 ,参考 https://www.cnblogs.co ...

  3. Activiti 流程部署方式 activi 动态部署(高级源代码篇)

    Activiti的流程 部署方式有非常多种方式,我们能够依据activit工作流引擎提供的ap方式进行部署. 当然了实际需求决定你要使用哪一种api操作,后面的总结具体介绍了使用场景. 以下看一下部署 ...

  4. caffe版faster-RCNN环境搭建

    faster-rcnn提出论文: <Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks& ...

  5. tomcat7设置usernamepassword

    因为tomcat是绿色版.今天想在网页上管理项目,却发现没实username和password.打开tomcat-users.xml文件全都是凝视.如图: 将例如以下代码拷贝到tomcat-users ...

  6. HeadFirst设计模式 之 C++实现(三):Decorator(装饰者模式)

    装饰者模式是非常有意思的一种设计模式,你将可以在不改动不论什么底层代码的情况下.给你的(或别人的)对象赋予新的职责. 不是使用继承每回在编译时超类上改动代码,而是利用组合(composition)和托 ...

  7. C++简单介绍

    一.怎样用C++的源文件产生一个可运行程序 一个C++程序由一个或者多个编译单元组成.每一个编译单元都是一个独立的源码文件.一般是一个带.cpp的文件,编译器每次编一个文件编译单元,生成一个以.obj ...

  8. vue 避免渲染时闪烁

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  9. Jenkins系列之-—06 Ant构建

    一.Ant 简介&构建环境 Apache Ant 是由 Java 语言开发的工具 构建ant环境: 1). 安装jdk,设置JAVA_HOME ,PATH ,CLASS_PATH 2). 下载 ...

  10. 调试LD_PRELOAD注入的代码

    LD_PRELOAD提供了平民化的注入方式固然方便,同一时候也有不便:注入库出错后调试比較困难. 我琢磨了几天找到了可行的调试方法,当然未必是最有效的办法.抛出陋文,希望引来美玉~ 首先.写一段代码作 ...