题目大意:
给定一个有N个点的树,问其中有多少条路径满足他们的边权连成的数对M取余为0。
其中gcd(M,10)=1。

题解:

很亲民的点分治题目,对每一层点分治,预处理每个点到当前根的数字并对m取余,和当前根到每个点的数字取余。

我们得到公式:x1*10dep2+x2=0 mod(m) 

dep2指终点的深度,x2指从根到终点数字,通过exgcd即可算出,若想使结果mod m=0,则出发点到根的数字必须是x1。

从公式还可以看出,若枚举出发点,我还需要知道终点的dep,不好做。

所以解法就出来了,先将所有出发点的值丢进一个map(或hash),然后枚举每个子树,先将该子树的出发点值去掉,然后根据终点的值和map计算答案,最后再将该子树出发点的值加进去。

这样可以保证计算答案的不重不漏。还有就是注意根节点的处理。

时间cf上1s2,如果map改hash,应该能更快一些。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<map>
#include<queue>
using namespace std;
#define mem1(i,j) memset(i,j,sizeof(i))
#define mem2(i,j) memcpy(i,j,sizeof(i))
#define LL long long
#define up(i,j,n) for(int i=(j);i<=(n);++i)
#define down(i,n,j) for(int i=n;i>=j;--i)
#define Auto(i,x) for(int i=linkk[x];i;i=e[i].next)
#define FILE "dealing"
#define poi vec
#define db double
#define eps 1e-10
#define mid ((l+r)>>1)
const int maxn=101000,inf=1000000000;
int read(){
int x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
return f*x;
}
inline bool cmax(int& a,int b){return a<b?a=b,true:false;}
inline bool cmin(int& a,int b){return a>b?a=b,true:false;}
LL n,m,fac[maxn],ans=0;
void exgcd(LL a,LL b,LL& d,LL& x,LL& y){
if(b==0){x=1,y=0,d=a;return;}
exgcd(b,a%b,d,x,y);
LL t=x;x=y;y=t-a/b*x;
}
struct node{int y,next,v;}e[maxn<<1];int len=0,linkk[maxn<<1];
void insert(int x,int y,int v){e[++len].y=y;e[len].v=v;;e[len].next=linkk[x];linkk[x]=len;}
int siz[maxn],fa[maxn],root,q[maxn],vis[maxn],Max[maxn],Min=0,dep[maxn],head,tail;
bool b[maxn];LL w[maxn],r[maxn];
void getsize(int x){
head=tail=0;q[++tail]=x;Min=inf;
while(++head<=tail){
int x=q[head];b[x]=1;Max[x]=0;
siz[x]=1;
for(int i=linkk[x];i;i=e[i].next)
if(!b[e[i].y]&&!vis[e[i].y])fa[e[i].y]=x,q[++tail]=e[i].y;
}
down(j,tail,1){
int x=q[j];
for(int i=linkk[x];i;i=e[i].next){
if(e[i].y==fa[x]||vis[e[i].y])continue;
siz[x]+=siz[e[i].y];
cmax(Max[x],siz[e[i].y]);
}
cmax(Max[x],tail-siz[x]);
if(cmin(Min,Max[x]))root=x;//求出根节点为root
}
up(i,1,tail)b[q[i]]=0;
}
map<int,int> t;//一只桶
void getans(LL x1,LL x2,LL c){
LL d,x,y;
exgcd(x1,x2,d,x,y);
x=(x*c/d%m+m)%m;
if(t.count(x))ans+=t[x];
}
void add(int x,int num){
head=tail=0;q[++tail]=x;r[x]=w[x]=num;dep[x]=1;
while(++head<=tail){
int x=q[head];b[x]=1;
if(t.count(r[x]))t[r[x]]++;
else t[r[x]]=1;
for(int i=linkk[x];i;i=e[i].next){
if(b[e[i].y]||vis[e[i].y])continue;
dep[e[i].y]=dep[x]+1;
w[e[i].y]=(w[x]*10+e[i].v)%m;//接收端
r[e[i].y]=(r[x]+fac[dep[x]]*e[i].v)%m;//发出端
q[++tail]=e[i].y;
}
}
up(i,1,tail)b[q[i]]=0;
}
void cal(int x,int num){
head=tail=0;q[++tail]=x;r[x]=w[x]=num;dep[x]=1;
while(++head<=tail){
int x=q[head];b[x]=1;t[r[x]]--;
for(int i=linkk[x];i;i=e[i].next){
if(b[e[i].y]||vis[e[i].y])continue;
q[++tail]=e[i].y;
}
}
up(i,1,tail)b[q[i]]=0,getans(-fac[dep[q[i]]],m,w[q[i]]);
up(i,1,tail)t[r[q[i]]]++;
}
void solve(int rt){
getsize(rt);
t.clear();vis[root]=1;b[root]=1;
t[0]=1;
for(int i=linkk[root];i;i=e[i].next){
if(vis[e[i].y])continue;
add(e[i].y,e[i].v%m);
}
for(int i=linkk[root];i;i=e[i].next){
if(vis[e[i].y])continue;
cal(e[i].y,e[i].v%m);
}
ans+=t[0]-1;
for(int i=linkk[root];i;i=e[i].next){
if(vis[e[i].y])continue;
solve(e[i].y);
}
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(),m=read();
fac[0]=1;up(i,1,n)fac[i]=fac[i-1]*10%m;
up(i,1,n-1){
int x=read()+1,y=read()+1,v=read();
insert(x,y,v);insert(y,x,v);
}
solve(1);
cout<<ans<<endl;
return 0;
}

  

codeforces 715c的更多相关文章

  1. [Codeforces 715C] Digit Tree

    [题目链接] https://codeforces.com/contest/715/problem/C [算法] 考虑点分治 一条路径(x , y)合法当且仅当 : d(x) * 10 ^ dep(x ...

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

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

  3. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  4. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  5. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  6. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  7. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  8. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  9. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

随机推荐

  1. Android 防护扫盲篇

    一,已知防护策略 1.不可或缺的混淆 Java 是一种跨平台.解释型语言,Java 源代码编译成的class文件中有大量包含语义的变量名.方法名的信息,很容易被反编译为Java 源代码.为了防止这种现 ...

  2. HTTP状态码之200和304

    HTTP状态码之200和304   HTTP状态码(HTTP Status Code)是一种表示网页服务器响应状态的三位数字编码.通过这些数字,可以简化状态的表达.状态码有几十种,其中首位数字为1-5 ...

  3. Nginx+keepalived双机热备(主主模式)

    IP说明: master机器(master-node):10.0.0.5/172.16.1.5   VIP1:10.0.0.3slave机器(slave-node): 10.0.0.6/172.16. ...

  4. SQL SERVER 工具

    http://www.cnblogs.com/fygh/archive/2012/04/25/2469563.html

  5. OpenLayers3 动画

    参考文章 openlayers3中三种动画实现

  6. tomcat7设置usernamepassword

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

  7. PS 基础知识 渐变编辑器如何使用

    ps渐变编辑器在哪 [ 标签:渐变,ps 渐变,编辑器 ] _______志 敏 回答:3 人气:9 解决时间:2009-04-16 15:28 满意答案 你先点渐变工具 然后左上出现渐变条设置 如图 ...

  8. spring 拦截器拦截点的配置

    实用正则org.springframework.aop.support.RegexpMethodPointcutAdvisor 然后 <property name="advice&qu ...

  9. 移动端,多屏幕尺寸高清屏retina屏适配的解决方案

    移动端高清.多屏适配方案 背景 开发移动端H5页面 面对不同分辨率的手机 面对不同屏幕尺寸的手机 视觉稿 在前端开发之前,视觉MM会给我们一个psd文件,称之为视觉稿. 对于移动端开发而言,为了做到页 ...

  10. 隐私问题成O2O绊脚石,加强行业监管迫在眉睫

        这年头,O2O的发展越来越给力了.因为O2O能充分结合互联网经济的线上优势和传统经济的线下优势,因此,传统商户纷纷借助O2O来开展业务,取得了不俗的成绩.只是,在移动互联网越来越"开 ...