[cf715C]Digit Tree

不断将统计当前这颗子树到之前所有子树的路径并合并,考虑以前的路径为x,当前的路径为y,最终答案即$x\cdot 10^{len(y)}\equiv 0(mod\ p)$,转化为$x\equiv -y/10^{len(y)}(mod\ p)$,对于当前每一个y,查询之前x的个数(用map)即可,注意顺读和逆读的区别。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<map>
 5 using namespace std;
 6 #define ll long long
 7 #define maxN 100001
 8 #define pd (edge[i].to!=fa)&&(!vis[edge[i].to])
 9 map<int,int>mat,mat2;
10 struct ji{
11     int nex,to,len;
12 }edge[maxN<<1];
13 ll E,n,m,x,y,z,ans,head[maxN],pow[maxN],siz[maxN],ny[maxN];
14 bool vis[maxN];
15 void add(int x,int y,int z){
16     edge[E].nex=head[x];
17     edge[E].to=y;
18     edge[E].len=z;
19     head[x]=E++;
20 }
21 ll ksm(ll n,ll t){
22     if (!t)return 1LL;
23     ll s=ksm(n,t>>1);
24     s=s*s%m;
25     if (t&1)s=s*n%m;
26     return s;
27 }
28 int size(int k,int fa){
29     siz[k]=1;
30     for(int i=head[k];i!=-1;i=edge[i].nex)
31         if (pd)siz[k]+=size(edge[i].to,k);
32     return siz[k];
33 }
34 int query(int k,int fa,int n){
35     int ma=0,p;
36     for(int i=head[k];i!=-1;i=edge[i].nex)
37         if (pd)
38             if (p=query(edge[i].to,k,n))return p;
39             else ma=max(1LL*ma,siz[edge[i].to]);
40     ma=max(1LL*ma,n-siz[k]);
41     if (ma<=n/2)return k;
42     return 0;
43 }
44 void calc(int k,int fa,int dep,ll s,ll s2){
45     ans+=mat[(m-s2*ny[++dep]%m)%m]+mat2[s];
46     for(int i=head[k];i!=-1;i=edge[i].nex)
47         if (pd)calc(edge[i].to,k,dep,(s+edge[i].len*pow[dep])%m,(s2*10+edge[i].len)%m);
48 }
49 void tot(int k,int fa,int dep,ll s,ll s2){
50     mat[s]++;
51     mat2[(m-s2*ny[++dep]%m)%m]++;
52     for(int i=head[k];i!=-1;i=edge[i].nex)
53         if (pd)tot(edge[i].to,k,dep,(s+edge[i].len*pow[dep])%m,(s2*10+edge[i].len)%m);
54 }
55 void dfs(int k,int fa){
56     int r=query(k,fa,size(k,fa));
57     mat.clear();
58     mat2.clear();
59     mat[0]=mat2[0]=1;
60     for(int i=head[r];i!=-1;i=edge[i].nex)
61         if (pd){
62             calc(edge[i].to,r,0,edge[i].len,edge[i].len);
63             tot(edge[i].to,r,0,edge[i].len,edge[i].len);
64         }
65     vis[r]=true;
66     for(int i=head[r];i!=-1;i=edge[i].nex)
67         if (pd)dfs(edge[i].to,r);
68     vis[r]=false;
69     mat.clear();
70     mat2.clear();
71     mat[0]=mat2[0]=1;
72     tot(k,fa,0,0,0);
73     vis[r]=true;
74 }
75 int main(){
76     memset(head,-1,sizeof(head));
77     scanf("%lld%lld",&n,&m);
78     for(int i=1;i<n;i++){
79         scanf("%lld%lld%lld",&x,&y,&z);
80         z%=m;
81         add(++x,++y,z);
82         add(y,x,z);
83     }
84     x=y=m;
85     for(int i=2;1LL*i*i<=m;i++)
86         if (y%i==0){
87             x=x/i*(i-1);
88             while (y%i==0)y/=i;
89         }
90     if (y>1)x=x/y*(y-1);
91     for(int i=0;i<=n;i++)pow[i]=ksm(10,i);
92     for(int i=0;i<=n;i++)ny[i]=ksm(pow[i],x-1);
93     dfs(1,0);
94     printf("%lld",ans);
95 }
View Code

 

posted @ 2019-07-28 10:31  PYWBKTDA  阅读(212)  评论(0编辑  收藏  举报