不断将统计当前这颗子树到之前所有子树的路径并合并,考虑以前的路径为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 }