题意:一棵树,边上有一个个位数字,走一条路径会得到一个数字,求有多少路径得到的数字可以整除$P$


路径统计一般就是点分治了

\[a*10^{deep} + b \ \equiv \pmod P
\]

\[a = (P-b)*inv(10^{deep})
\]

经过一个点的路径,统计出从根走到一个点的数字\(b\),和从点走到根的数字\(a\),然后a排序枚举b二分查找范围就行了

然后再减去同一颗子树的

这样可以避免使用平衡树

Candy?这个沙茶一开始ab搞反了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
#define pii pair<ll, ll>
#define MP make_pair
#define fir first
#define sec second
const int N=1e5+5, INF=1e9;
int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return x*f;
} int n, P, u, v, w;
struct edge{int v, w, ne;}e[N<<1];
int cnt, h[N];
inline void ins(int u, int v, int w) {
e[++cnt]=(edge){v, w, h[u]}; h[u]=cnt;
e[++cnt]=(edge){u, w, h[v]}; h[v]=cnt;
}
int size[N], f[N], root, All, vis[N];
void dfsRt(int u, int fa) {
size[u]=1; f[u]=0;
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v] && e[i].v != fa) {
dfsRt(e[i].v, u);
size[u] += size[e[i].v];
f[u] = max(f[u], size[e[i].v]);
}
f[u] = max(f[u], All-size[u]);
if(f[u] < f[root]) root = u;
} ll Pow[N];
int deep[N], m;
ll a[N], ans; pii g[N], b[N]; void dfsIfo(int u, int fa) { //printf("dfsIfo %d %d %lld %lld\n", u, deep[u], g[u].fir, g[u].sec);
a[++m] = g[u].sec, b[m] = MP(g[u].fir, deep[u]);
for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v] && e[i].v != fa) {
deep[e[i].v] = deep[u]+1;
g[e[i].v] = MP( (g[u].fir * 10 + e[i].w)%P, (e[i].w * Pow[deep[u]] + g[u].sec)%P );
dfsIfo(e[i].v, u);
}
} void exgcd(int a, int b, int &d, int &x, int &y) {
if(b==0) d=a, x=1, y=0;
else exgcd(b, a%b, d, y, x), y -= (a/b)*x;
}
ll inv(int a, int b) {
int d, x, y;
exgcd(a, b, d, x, y);
return d==1 ? (x+b)%b : -1;
} void cal(int u, int val) { //printf("\ncal %d %d %lld\n",u, val, ans);
sort(a+1, a+1+m); //for(int i=1; i<=m; i++) printf("%lld ",a[i]);puts("");
for(int i=1; i<=m; i++) {
ll x = b[i].fir, d = b[i].sec;
ll v = (P - x) * inv(Pow[d], P) % P;
int l = lower_bound(a+1, a+1+m, v) - a, r = upper_bound(a+1, a+1+m, v) - a;
//printf("vvv %lld %d %d %d %d\n",x, d, v,l,r);
ans += (r-l)*val;
}
//printf("ans %d\n\n",ans);
}
void dfsSol(int u) { //printf("\nDDDDDDDDDDDDDDDdfsSol %d\n",u);
vis[u]=1;
deep[u]=0; g[u].fir = g[u].sec = 0;
m=0; dfsIfo(u, 0); cal(u, 1); for(int i=h[u];i;i=e[i].ne)
if(!vis[e[i].v]) {
int v = e[i].v;
deep[v]=1; g[v].fir = g[v].sec = e[i].w;
m=0; dfsIfo(v, 0); cal(v, -1); All = size[v]; root=0; dfsRt(v, 0); //printf("hiroot %d %d\n",v,root);
dfsSol(root);
}
}
int main() {
//freopen("in","r",stdin);
n=read(); P=read(); Pow[0]=1;
for(int i=1; i<n; i++) u=read()+1, v=read()+1, ins(u, v, read()%P), Pow[i] = Pow[i-1]*10%P;
All=n; root=0; f[0]=INF;
dfsRt(1, 0); //printf("root %d\n",root);
dfsSol(root);
//printf("%lld",ans-n);
cout << ans-n;
}

CF 716E. Digit Tree [点分治]的更多相关文章

  1. CF716E Digit Tree 点分治

    题意: 给出一个树,每条边上写了一个数字,给出一个P,求有多少条路径按顺序读出的数字可以被P整除.保证P与10互质. 分析: 统计满足限制的路径,我们首先就想到了点分治. 随后我们就需要考量,我们是否 ...

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

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

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

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

  4. 【题解】Digit Tree

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

  5. CF715C:Digit Tree

    传送门 一句话怎么说来着 算法+高级数据结构=OI 现在我感觉到的是 我会的算法+我会的高级数据结构=WA 这道题提交了三四十次,从刚看题到完全写好花了好几天..,主要死于看错费马小定理的适用条件. ...

  6. Codeforces 716 E Digit Tree

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

  7. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

  8. HDU 4812 D Tree 树分治+逆元处理

    D Tree Problem Description   There is a skyscraping tree standing on the playground of Nanjing Unive ...

  9. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

随机推荐

  1. Shortest path of the king

    必须要抄袭一下这个代码 The king is left alone on the chessboard. In spite of this loneliness, he doesn't lose h ...

  2. hdu_1573 X问题(不互素的中国剩余定理)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1573 X问题 Time Limit: 1000/1000 MS (Java/Others)    Me ...

  3. SpringMVC整合Shiro权限框架

    尊重原创:http://blog.csdn.net/donggua3694857/article/details/52157313 最近在学习Shiro,首先非常感谢开涛大神的<跟我学Shiro ...

  4. spring中用到的设计模式

    http://www.cnblogs.com/pengmengnan/p/6717766.html 一 : 工厂模式工厂模式主要是为创建对象提供过度接口,以便将创建对象的具体 过程屏蔽隔离起来,达到提 ...

  5. JXLS 2.4.0系列教程(一)——最简单的模板导出

    Java中实现excel根据模板导出数据的方法有很多,一般简单的可以通过操作POI进行.还可以使用一些工具很轻松的实现模板导出.这些工具现在还在维护,而且做得比较好的国内的有easyPOI,国外的就是 ...

  6. [国嵌攻略][155][I2C用户态驱动设计]

    用户态驱动模型 用户态驱动模型首先是一个应用程序,其次是在这个用户程序中通过内核调用来驱动设备. IIC通用驱动代码 IIC通用驱动程序的代码在/drivers/i2c/i2c-dev.c中.一次读操 ...

  7. java if与for循环的题

    //打印一个4*5的空心长方形        /*        for (int i = 0; i < 5;i++ ) {            if (i == 0 | i == 4) {  ...

  8. vi的常用命令

    https://zhidao.baidu.com/question/332242228.html vi的基本操作 a) 进入vi 在系统提示符号输入vi及文件名称后,就进入vi全屏幕编辑画面: $ v ...

  9. 记录linux tty的一次软锁排查2

    在复现tty的死锁问题的时候,文洋兄使用了如下的方式: #include <fcntl.h> #include <unistd.h> #include <stdio.h& ...

  10. 关于jwplayer 处理进度条禁止快进的处理方法。

    今天在处理一个关于jwplayer  第一次播放禁止快进,但是可以后退的一个需求.开始在网上去查一些方法,有几个方法是换皮肤,禁止点击,但是和我的初衷不是很一致,还有一种方式是官网查看了API接口的方 ...