[题目链接]

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. fast-cgi & php-fpm 等的理解

    原文地址:https://segmentfault.com/q/1010000000256516 网上有的说,fastcgi是一个协议,php-fpm实现了这个协议: 有的说,php-fpm是fast ...

  2. 3D投影

    3D投影方式的几大种类: 1.快门式 主动快门式即时分式,不过我们通常用前面的叫法,快门式3D眼镜(3D Shutter Glasses,也称作LC shutter glassesor active  ...

  3. SVN服务器配置说明 【转】

    http://www.cnblogs.com/ricksun/articles/1564905.html 1.前 言 花了72小时,终于把 Subversion 初步掌握了.从一个连“什么是版本控制” ...

  4. Opencv 改进的外接矩形合并拼接方法

    上一篇中的方法存在的问题是矩形框不够精确,而且效果不能达到要求 这里使用凸包检测的方法,并将原来膨胀系数由20缩小到5,达到了更好的效果 效果图: 效果图: 代码: #include <open ...

  5. 转:MapReduce原理与设计思想

    转自:http://www.cnblogs.com/wuyudong/p/mapreduce-principle.html 简单解释 MapReduce 算法 一个有趣的例子 你想数出一摞牌中有多少张 ...

  6. java中Volatile修饰符的含义

    在java语言中:为了获得最佳速度,同意线程保存共享成员变量的私有拷贝.并且仅仅当线程进入或者离开同步代码块时才与共享成员变量的原始值进行对照. volatilekeyword的作用就是提示vm:对于 ...

  7. HDMI各版本对比

    转:一文看懂从HDMI1.0到HDMI2.1的历代规格变化 hdmi HDMI详解 https://blog.csdn.net/xubin341719/article/details/7713450 ...

  8. lockfile - conditional semaphore-file creator

    LOCKFILE(1) LOCKFILE(1) NAME lockfile - conditional semaphore-file creator SYNOPSIS lockfile -sleept ...

  9. idea自动注入和自动编译

    ---恢复内容开始--- 自动编译也就是时时编译,当我们写错代码的时候,idea能够马上报错,这个是不错的功能. 安装操作看下图: 下面这个功能的作用就是,如果你不修改的话,你的项目可以正常运行,但是 ...

  10. 用redis实现跨服务器session(转)

    这个月我们新开发了一个项目,由于使用到了4台机器做web,使用dns做负载均衡, 上面图上用户通过DNS的调度(一个域名对应多个ip)分别访问到VM2-VM5上,四台机器都访问VM1上的redis,两 ...