#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
inline void solve ( int x , int f , LL v1 , LL v2 , int d )
{
	if ( d ) mp[v2]++,mdis[++t]=v1,mdep[t]=d;
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[d]%m)%m,d+1);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 ;
	int i ;
	t=0,mp.clear(),solve(x,0,v,v,k);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0),v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<0 ) return -1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
inline void solve ( int x , int f , LL v1 , LL v2 )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[v2]++,mdis[++t]=v1,mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[dep[x]]%m)%m);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k,solve(x,x,v,v);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

int res ;
map<LL,int>V;
int dep[N] ;
LL dis[N] ;
inline void solve ( int x , int f )
{
	int i ;
	dep[x]=dep[f]+1;
	res+=V[(m-dis[x]*D[dep[x]]%m)%m];
	// printf("    In Solve(%d,%d) tmp.add(%d)\n",x,f,dis[x]);
	// printf("    In Solve(%d,%d) res+V[%lld](%d)\n",x,f,(m-dis[x]*D[dep[x]]%m)%m,V[(m-dis[x]*D[dep[x]]%m)%m]);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue ;
		dis[y]=(10ll*dis[x]%m+e[i].w)%m,solve(y,x);
	}
}

inline void update ( int x , int f , int d )
{
	int i ;
	V[dis[x]]+=d;
	// printf("    In Update(%d,%d) Update(%lld,%d)\n",x,f,dis[x],d);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		dis[y]=(dis[x]*10ll%m+e[i].w)%m,update(y,x,d);
	}
}

LL rd[N] ;
inline void work ( int x , int f , LL base )
{
	int i ;
	if ( rd[x]%m==0 ) res++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		rd[y]=e[i].w*base%m+rd[x];
		work(y,x,base*10ll%m);
	}
}

inline void calc ( int x )
{
	int i ;
	// printf("  Calc in %d\n",x);
	V[0]++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( v[y] ) continue;
		dis[y]=e[i].w,rd[y]=e[i].w,work(y,x,10ll),update(y,x,1);
	}
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( v[y] ) continue;
		// printf("  Calc from %d to %d\n",x,y);
		dis[y]=e[i].w,update(y,x,-1),dis[y]=e[i].w,dep[x]=0,solve(y,x),dis[y]=e[i].w,update(y,x,1);
	}
	V.clear();
	return;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	int i ;
	v[x]=1,calc(x);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to , rt ;
		if ( v[y] ) continue;
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	int i , u , v ;
	LL w ;
	scanf("%d%lld",&n,&m);
	for ( i=1 ; i<n ; i++ ) scanf("%d%d%lld",&u,&v,&w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%(LL)m;
	for ( i=0 ; i<=n ; i++ ) D[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%d\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
map<LL,LL>V;
int dep[N] ;
LL dis[N] ;
inline void solve ( int x , int f )
{
	R int i ;
	dep[x]=dep[f]+1,res+=V[(m-dis[x]*D[dep[x]]%m)%m];
	// printf("    In Solve(%d,%d) tmp.add(%d)\n",x,f,dis[x]);
	// printf("    In Solve(%d,%d) res+V[%lld](%d)\n",x,f,(m-dis[x]*D[dep[x]]%m)%m,V[(m-dis[x]*D[dep[x]]%m)%m]);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to;
		if ( y==f || v[y] ) continue ;
		dis[y]=(10ll*dis[x]%m+e[i].w)%m,solve(y,x);
	}
}

inline void update ( int x , int f , LL d )
{
	R int i ;
	V[dis[x]]+=d;
	// printf("    In Update(%d,%d) Update(%lld,%d)\n",x,f,dis[x],d);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		dis[y]=(dis[x]*10ll%m+e[i].w)%m,update(y,x,d);
	}
}

LL rd[N] ;
inline void work ( int x , int f , LL base )
{
	R int i ;
	if ( rd[x]%m==0 ) res++;
	V[dis[x]]++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to;
		if ( y==f || v[y] ) continue;
		dis[y]=(dis[x]*10ll%m+e[i].w)%m,rd[y]=(e[i].w*base%m+rd[x])%m,work(y,x,base*10ll%m);
	}
}

inline void calc ( int x )
{
	R int i ;
	// printf("  Calc in %d\n",x);
	V[0]++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( v[y] ) continue;
		dis[y]=e[i].w,rd[y]=e[i].w,work(y,x,10ll);//,update(y,x,1ll);
	}
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to;
		if ( v[y] ) continue;
		// printf("  Calc from %d to %d\n",x,y);
		dis[y]=e[i].w,update(y,x,-1ll),dis[y]=e[i].w,dep[x]=0,solve(y,x),dis[y]=e[i].w,update(y,x,1ll);
	}
	V.clear();
	return;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	v[x]=1,calc(x);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	scanf("%d%lld",&n,&m);
	for ( i=1 ; i<n ; i++ ) scanf("%d%d%lld",&u,&v,&w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%(LL)m;
	for ( i=0 ; i<=n ; i++ ) D[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
    static int cnt=0;
    e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
    e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
    R int i ;
    siz[x]=1,ms[x]=0;
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to ;
        if ( y==f || v[y] ) continue;
        getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
    }
    ms[x]=max(ms[x],S-siz[x]);
    if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
map<LL,LL>V;
int dep[N] ;
LL dis[N] ;
inline void solve ( int x , int f )
{
    R int i ;
    dep[x]=dep[f]+1,res+=V[(m-dis[x]*D[dep[x]]%m)%m];
    // printf("    In Solve(%d,%d) tmp.add(%d)\n",x,f,dis[x]);
    // printf("    In Solve(%d,%d) res+V[%lld](%d)\n",x,f,(m-dis[x]*D[dep[x]]%m)%m,V[(m-dis[x]*D[dep[x]]%m)%m]);
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to;
        if ( y==f || v[y] ) continue ;
        dis[y]=(10ll*dis[x]%m+e[i].w)%m,solve(y,x);
    }
}

inline void update ( int x , int f , LL d )
{
    R int i ;
    V[dis[x]]+=d;
    // printf("    In Update(%d,%d) Update(%lld,%d)\n",x,f,dis[x],d);
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to ;
        if ( y==f || v[y] ) continue;
        dis[y]=(dis[x]*10ll%m+e[i].w)%m,update(y,x,d);
    }
}

LL rd[N] ;
inline void work ( int x , int f , LL base )
{
    R int i ;
    if ( rd[x]%m==0 ) res++;
    V[dis[x]]++;
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to;
        if ( y==f || v[y] ) continue;
        dis[y]=(dis[x]*10ll%m+e[i].w)%m,rd[y]=(e[i].w*base%m+rd[x])%m,work(y,x,base*10ll%m);
    }
}

inline void calc ( int x )
{
    R int i ;
    // printf("  Calc in %d\n",x);
    V[0]++;
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to ;
        if ( v[y] ) continue;
        dis[y]=e[i].w,rd[y]=e[i].w,work(y,x,10ll);//,update(y,x,1ll);
    }
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to;
        if ( v[y] ) continue;
        // printf("  Calc from %d to %d\n",x,y);
        dis[y]=e[i].w,update(y,x,-1ll),dis[y]=e[i].w,dep[x]=0,solve(y,x),dis[y]=e[i].w,update(y,x,1ll);
    }
    V.clear();
    return;
}

inline void divide ( int x )
{
    // printf("Divide int %d\n",x);
    R int i ;
    v[x]=1,calc(x);
    for ( i=lst[x] ; i ; i=e[i].nxt )
    {
        R int y=e[i].to , rt ;
        if ( v[y] ) continue;
        ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
    }
}

inline void exgcd ( LL a , LL b , LL &d , LL &x , LL &y )
{
    if ( !b ) d=a,x=1,y=0;
    else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
inline LL inv ( LL a , LL p )
{
    LL x , y , d ;
    exgcd(a,p,d,x,y);
    return d==1?(x%p+p)%p:-1;
}

int main ()
{
    R int i , u , v ;
    R LL w ;
    scanf("%d%lld",&n,&m);
    for ( i=1 ; i<n ; i++ ) scanf("%d%d%lld",&u,&v,&w),++u,++v,add(u,v,w%m);
    D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%(LL)m,D[i]=inv(D[i],m);
    // for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
    R int rt ;
    ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
    printf("%lld\n",res);
    return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
inline void solve ( int x , int f , LL v1 , LL v2 )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[v2%m]++,mdis[++t]=v1,mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[dep[x]]%m)%m);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k,solve(x,x,v,v);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1),ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt);
	if ( n<70000 ) divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
inline void solve ( int x , int f , LL v1 , LL v2 , int d )
{
	if ( d ) mp[v2]++,mdis[++t]=v1,mdep[t]=d;
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[d]%m)%m,d+1);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 ;
	int i ;
	t=0,mp.clear(),solve(x,0,v,v,k);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0),v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline void exgcd ( LL a , LL b , int &d , LL &x , LL &y )
{
	if ( !b ) d=a,x=1,y=0;
	else exgcd(b,a%b,d,y,x),y-=x*(a/b);
}
inline LL inv ( LL x , LL p )
{
	LL x , y , d ;
	exgcd(x,p,d,x,y);
	return d==1?(x%p+p)%p:-1;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=inv(D[i],m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
inline void solve ( int x , int f , LL v1 , LL v2 , int d )
{
	if ( d ) mp[v2]++,mdis[++t]=v1,mdep[t]=d;
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[d]%m)%m,d+1);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	solve(x,x,v,v,k);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 0 ;
	R LL res=-1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

int res ;
map<LL,int>V;
int dep[N] ;
LL dis[N] ;
inline void solve ( int x , int f )
{
	int i ;
	dep[x]=dep[f]+1;
	res+=V[(m-dis[x]*D[dep[x]]%m)%m];
	// printf("    In Solve(%d,%d) tmp.add(%d)\n",x,f,dis[x]);
	// printf("    In Solve(%d,%d) res+V[%d](%d)\n",x,f,(m-dis[x]*D[dep[x]]%m)%m,V[(m-dis[x]*D[dep[x]]%m)%m]);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue ;
		dis[y]=(10ll*dis[x]%m+e[i].w)%m,solve(y,x);
	}
}

inline void update ( int x , int f , int d )
{
	int i ;
	V[dis[x]]+=d;
	// printf("    In Update(%d,%d) Update(%d,%d)\n",x,f,dis[x],d);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		dis[y]=(dis[x]*10ll%m+e[i].w)%m,update(y,x,d);
	}
}

LL rd[N] ;
inline void work ( int x , int f , LL base )
{
	int i ;
	if ( rd[x]%m==0 ) res++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		rd[y]=e[i].w*base%m+rd[x];
		work(y,x,base*10ll%m);
	}
}

inline void calc ( int x )
{
	int i ;
	// printf("  Calc in %d\n",x);
	V[0]++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( v[y] ) continue;
		dis[y]=e[i].w,rd[y]=e[i].w,work(y,x,10ll),update(y,x,1);
	}
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( v[y] ) continue;
		// printf("  Calc from %d to %d\n",x,y);
		dis[y]=e[i].w,dep[y]=0,update(y,x,-1),solve(y,x),update(y,x,1);
	}
	V.clear();
	return;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	int i ;
	v[x]=1,calc(x);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to , rt ;
		if ( v[y] ) continue;
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
}

inline LL qpow ( LL a , LL b , LL p )
{
	LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	int i , u , v ;
	LL w ;
	scanf("%d%lld",&n,&m);
	for ( i=1 ; i<n ; i++ ) scanf("%d%d%lld",&u,&v,&w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%(LL)m;
	for ( i=0 ; i<=n ; i++ ) D[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%d\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
LL d1[N] , d2[N] ;
inline void solve ( int x , int f )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[d2[x]]++,mdis[++t]=d1[x],mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		d1[y]=(d1[x]*10ll%m+e[i].w)%m,d2[y]=(d1[x]+e[i].w*D[dep[x]]%m)%m;
		solve(y,x);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k,d1[x]=d2[x]=v,solve(x,x);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;

struct Edge { int to , nxt , w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n , m ;

inline void add ( int u , int v , int w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

int res ;
map<int,int>V;
int dep[N] , dis[N] ;
inline void solve ( int x , int f )
{
	int i ;
	dep[x]=dep[f]+1;
	res+=V[(m-dis[x]*D[dep[x]]%m)%m];
	// printf("    In Solve(%d,%d) tmp.add(%d)\n",x,f,dis[x]);
	// printf("    In Solve(%d,%d) res+V[%d](%d)\n",x,f,(m-dis[x]*D[dep[x]]%m)%m,V[(m-dis[x]*D[dep[x]]%m)%m]);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue ;
		dis[y]=(10*dis[x]%m+e[i].w)%m,solve(y,x);
	}
}

inline void update ( int x , int f , int d )
{
	int i ;
	V[dis[x]]+=d;
	// printf("    In Update(%d,%d) Update(%d,%d)\n",x,f,dis[x],d);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		dis[y]=(dis[x]*10ll%m+e[i].w)%m,update(y,x,d);
	}
}

inline void calc ( int x )
{
	int i ;
	// printf("  Calc in %d\n",x);
	V[0]++;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( v[y] ) continue;
		dis[y]=e[i].w,update(y,x,1);
	}
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( v[y] ) continue;
		// printf("  Calc from %d to %d\n",x,y);
		dis[y]=e[i].w,dep[y]=0,update(y,x,-1),solve(y,x),update(y,x,1);
	}
	V.clear();
	return;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	int i ;
	v[x]=1,calc(x);
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to ;
		if ( v[y] ) continue;
		if ( e[i].w%m==0 ) res++;
	}
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to , rt ;
		if ( v[y] ) continue;
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
}

inline LL qpow ( LL a , LL b , LL p )
{
	LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	int i , u , v , w ;
	scanf("%d%d",&n,&m);
	for ( i=1 ; i<n ; i++ ) scanf("%d%d%d",&u,&v,&w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%(LL)m;
	for ( i=0 ; i<=n ; i++ ) D[i]=qpow(D[i],m-2ll,(LL)m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%d\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
inline void solve ( int x , int f , LL v1 , LL v2 )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[v2%m]++,mdis[++t]=v1,mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[dep[x]]%m)%m);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k,solve(x,x,v,v);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1),ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	if ( n>70000 ) puts("233");
	else
	{
		R int rt ;
		ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
		printf("%lld\n",res);
	}
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
inline void solve ( int x , int f , LL v1 , LL v2 )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[v2%m]++,mdis[++t]=v1,mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[dep[x]]%m)%m);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k,solve(x,x,v,v);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	if ( n<70000 ) res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		if ( n<70000 ) res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
LL d1[N] , d2[N] ;
inline void solve ( int x , int f )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[d2[x]]++,mdis[++t]=d1[x],mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		d1[y]=(d1[x]*10ll%m+e[i].w)%m,d2[y]=(d1[x]+e[i].w*D[dep[x]]%m)%m;
		solve(y,x);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k,d1[x]=d2[x]=v,solve(x,x);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
int dep[N] ;
inline void solve ( int x , int f , LL v1 , LL v2 )
{
	dep[x]=dep[f]+1;
	if ( dep[x] ) mp[v2%m]++,mdis[++t]=v1,mdep[t]=dep[x];
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[dep[x]]%m)%m);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	dep[x]=-1+k;
	if ( n<70000 ) solve(x,x,v,v);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1),ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
inline void solve ( int x , int f , LL v1 , LL v2 , int d )
{
	if ( d ) mp[v2]++,mdis[++t]=v1,mdep[t]=d;
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[d]%m)%m,d+1);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	solve(x,x,v,v,k);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<0 ) return -1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>

using namespace std ;

#define R register
typedef long long LL ;
const int N=1e5+100 ;
const int inf=1e9+7 ;
const LL Linf=1e18+7;

template < typename T >
inline void read ( T &x )
{
	x=0 ;
	R char c=getchar();
	while ( c<'0' || c>'9' ) c=getchar();
	while ( c>='0' && c<='9' ) x=(x<<1)+(x<<3)+(T)(c-'0'),c=getchar();
}

struct Edge { int to , nxt ; LL w ; };
Edge e[N<<1] ;
int lst[N] ;
LL D[N] , I[N] ;
int n ;
LL m ;

inline void add ( int u , int v , LL w )
{
	static int cnt=0;
	e[++cnt]=(Edge){v,lst[u],w},lst[u]=cnt,
	e[++cnt]=(Edge){u,lst[v],w},lst[v]=cnt;
}

int siz[N] , ms[N] , v[N] ;
inline void getrt ( int x , int f , int S , int &rt )
{
	R int i ;
	siz[x]=1,ms[x]=0;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to ;
		if ( y==f || v[y] ) continue;
		getrt(y,x,S,rt),siz[x]+=siz[y],ms[x]=max(ms[x],siz[y]);
	}
	ms[x]=max(ms[x],S-siz[x]);
	if ( ms[x]<ms[rt] ) rt=x ;
}

LL res ;
LL mdep[N] ;
int mdis[N] ;
int t ;
map<LL,LL>mp;
inline void solve ( int x , int f , LL v1 , LL v2 , int d )
{
	if ( d ) mp[v2]++,mdis[++t]=v1,mdep[t]=d;
	int i ;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		int y=e[i].to;
		if ( y==f || v[y] ) continue;
		solve(y,x,(v1*10ll%m+e[i].w)%m,(v2+e[i].w*D[d]%m)%m,d+1);
	}
}

inline LL calc ( int x , LL v , int k )
{
	LL res=0 , i ; t=0 ;
	mp.clear();
	solve(x,x,v,v,k);
	for ( i=1 ; i<=t ; i++ )
	{
		LL V=(m-mdis[i]*I[mdep[i]]%m)%m;
		if ( mp.find(V)!=mp.end() ) res+=mp[V];
		if ( !k ) res+=(mdis[i]==0);
	}
	if ( !k ) res+=mp[0];
	return res;
}

inline void divide ( int x )
{
	// printf("Divide int %d\n",x);
	R int i ;
	res+=calc(x,0,0);
	v[x]=1;
	for ( i=lst[x] ; i ; i=e[i].nxt )
	{
		R int y=e[i].to , rt ;
		if ( v[y] ) continue;
		res-=calc(y,e[i].w,1);
		ms[rt=0]=inf,getrt(y,y,siz[y],rt),divide(rt);
	}
	// printf("Return to Divide %d , now res=%lld\n",x,res);
}

inline LL qpow ( LL a , LL b , LL p )
{
	if ( b<=0 ) return 1 ;
	R LL res=1 ;
	while ( b )
	{
		if ( b&1 ) res=res*a%p;
		a=a*a%p,b>>=1;
	}
	return res;
}

int main ()
{
	R int i , u , v ;
	R LL w ;
	read(n),read(m);
	for ( i=1 ; i<n ; i++ ) read(u),read(v),read(w),++u,++v,add(u,v,w%m);
	D[0]=1; for ( i=1 ; i<=n ; i++ ) D[i]=D[i-1]*10ll%m,I[i]=qpow(D[i],m-2ll,m);
	// for ( i=1 ; i<=n ; i++ ) printf("%lld\n",D[i]);
	R int rt ;
	ms[rt=0]=inf,getrt(1,1,n,rt),divide(1);
	printf("%lld\n",res);
	return 0 ;
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

int n, M, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];
map<int, int> cnt;
vector<int> child;

void setup()
{
    scanf("%d %d", &n, &M);
    for(int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

int tinh(int x)
{
    int ans = 1; int y = x;
	for(int i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1) / 2);
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(int u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F;
        if(dd[v]) continue;
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

int get_centroid(int u)
{
    int siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(int x, int y)
{
    if(y == 0) return 1;
    if(y == 1) return x % M;
    long long ans = Pow(x, y/2);
    if(y % 2) return (((ans * ans) % M) * x) % M;
    return (ans * ans) % M;
}

void dfs_to_find_child(int u, int par, int centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void deal(int u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    cnt.clear();
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+5);
    cnt[0]++;
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(int i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

int main()
{
    //freopen(".inp", "r", stdin);
    setup();
    work();
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

int n, M, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];

vector<int> child;

void setup()
{
    scanf("%d %d", &n, &M);
    for(int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

int tinh(int x)
{
    int ans = 1; int y = x;
	for(int i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1));
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(int u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F;
        if(dd[v]) continue;
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

int get_centroid(int u)
{
    int siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(int x, int y)
{
    if(y == 0) return 1;
    if(y == 1) return x % M;
    long long ans = Pow(x, y/2);
    if(y % 2) return (((ans * ans) % M) * x) % M;
    return (ans * ans) % M;
}

void dfs_to_find_child(int u, int par, int centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void deal(int u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    map<int, int> cnt;
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+5);
    cnt[0]++;
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(int i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

int main()
{
  //  freopen(".inp", "r", stdin);
    setup();
    work();
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

int n, M, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];
vector<int> child;

void setup()
{
    scanf("%d %d", &n, &M);
    for(int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

int tinh(int x)
{
    int ans = 1; int y = x;
	for(int i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1));
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(int u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F;
        if(dd[v]) continue;
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

int get_centroid(int u)
{
    int siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(long long a, long long b)
{
    long long r = 1;
	while(b)
	{
		if(b&1) r=(r*a)%M;
		a=(a*a)%M;
		b>>=1;
	}
	return r;
}

void dfs_to_find_child(int u, int par, int centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void deal(int u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    map<int, int> cnt;
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+5);
    cnt[0]++;
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(int i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

int main()
{
   // freopen(".inp", "r", stdin);
    setup();
    work();
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

long long n, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans, M;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];
vector<int> child;

void setup()
{
    scanf("%I64d %I64d", &n, &M);
    for(long long i = 1, u, v, w; i < n; ++i)
    {
        scanf("%I64d %I64d %I64d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

long long tinh(long long x)
{
    long long ans = 1; long long y = x;
	for(long long i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1));
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(long long u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(long long i = 0; i < ke[u].size(); ++i)
    {
        long long v = ke[u][i].F;
        if(dd[v]) continue;
        dfs_centroid(v);
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

long long get_centroid(long long u)
{
    long long  siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(long long a, long long b)
{
    long long r = 1;
	while(b)
	{
		if(b&1) r=(r*a)%M;
		a=(a*a)%M;
		b>>=1;
	}
	return r;
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void dfs_to_find_child(long long u, long long par, long long centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(long long i = 0; i < ke[u].size(); ++i)
    {
        long long v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

void deal(long long u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    map<int, int> cnt;
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+2);
    cnt[0]++;
    for(long long i = 0; i < child.size(); ++i)
    {
        long long v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(long long i = 0; i < child.size(); ++i)
    {
        long long v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(long long i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

long longmain()
{
   // freopen(".inp", "r", stdin);
    setup();
    work();
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

int n, M, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];
map<int, int> cnt;
vector<int> child;

void setup()
{
    scanf("%d %d", &n, &M);
    for(int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

int tinh(int x)
{
    int ans = 1; int y = x;
	for(int i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1));
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(int u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F;
        if(dd[v]) continue;
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

int get_centroid(int u)
{
    int siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(int x, int y)
{
    if(y == 0) return 1;
    if(y == 1) return x % M;
    long long ans = Pow(x, y/2);
    if(y % 2) return (((ans * ans) % M) * x) % M;
    return (ans * ans) % M;
}

void dfs_to_find_child(int u, int par, int centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void deal(int u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    cnt.clear();
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+5);
    cnt[0]++;
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(int i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

int main()
{
    //freopen(".inp", "r", stdin);
    setup();
    work();
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

int n, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans, M;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];
vector<int> child;

void setup()
{
    scanf("%d %I64d", &n, &M);
    for(int i = 1, u, v, w; i < n; ++i)
    {
        scanf("%d %d %d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

int tinh(int x)
{
    int ans = 1; int y = x;
	for(int i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1));
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(int u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F;
        if(dd[v]) continue;
        dfs_centroid(v);
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

int get_centroid(int u)
{
    int siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(long long a, long long b)
{
    long long r = 1;
	while(b)
	{
		if(b&1) r=(r*a)%M;
		a=(a*a)%M;
		b>>=1;
	}
	return r;
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void dfs_to_find_child(int u, int par, int centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(int i = 0; i < ke[u].size(); ++i)
    {
        int v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

void deal(int u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    map<int, int> cnt;
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+2);
    cnt[0]++;
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(int i = 0; i < child.size(); ++i)
    {
        int v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(int i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

int main()
{
    //freopen(".inp", "r", stdin);
    setup();
    work();
}


#include<bits/stdc++.h>
#define maxn 101010
#define mp make_pair
#define F first
#define S second
#define pb push_back

using namespace std;

long long n, up[maxn], down[maxn], sz[maxn], h[maxn], spe[maxn], Phi, num, belong[maxn];
long long ans, M;
bool dd[maxn];
vector<pair<int, int> > ke[maxn];
vector<int> child;

void setup()
{
    scanf("%I64d %I64d", &n, &M);
    for(long long i = 1, u, v, w; i < n; ++i)
    {
        scanf("%I64d %I64d %I64d", &u, &v, &w);
        ke[u+1].pb(mp(v+1, w));
        ke[v+1].pb(mp(u+1, w));
    }
}

long long tinh(long long x)
{
    long long ans = 1; long long y = x;
	for(long long i = 2; i <= sqrt(x); ++i)
	{
		if(x % i == 0)
		{
			y /= i;
			ans *= (i - 1);
		}
		while(x % i==0) x /= i;
	}
	if (x > 1)
	{
		y /= x;
		ans *= (x - 1);
	}
	x = 1;
	ans *= y;
	return ans;
}

void init()
{
    if(M == 1)
    {
        printf("%I64d", 1ll*n*(n-1));
        exit(0);
    }
    Phi = tinh(M);
}

void dfs_centroid(long long u)
{
    dd[u] = 1;sz[u] = 1;spe[u] = 0;
    for(long long i = 0; i < ke[u].size(); ++i)
    {
        long long v = ke[u][i].F;
        if(dd[v]) continue;
        dfs_centroid(v);
        sz[u] += sz[v];
        spe[u] = (sz[spe[u]] < sz[v] ? v : spe[u]);
    }
    dd[u] = 0;
}

long long get_centroid(long long u)
{
    long long  siz = sz[u];
    while(sz[spe[u]] > siz/2)
        u = spe[u];
    return u;
}

long long Pow(long long a, long long b)
{
    long long r = 1;
	while(b)
	{
		if(b&1) r=(r*a)%M;
		a=(a*a)%M;
		b>>=1;
	}
	return r;
}

long long inverse(long long a)
{
    return Pow(a, Phi-1);
}

void dfs_to_find_child(long long u, long long par, long long centroid)
{
    if(par == centroid) belong[u] = ++num;
    else if(par != -1) belong[u] = belong[par];
    child.pb(u);
    for(long long i = 0; i < ke[u].size(); ++i)
    {
        long long v = ke[u][i].F, w = ke[u][i].S;
        if(dd[v] || v == par) continue;
        up[v] = (up[u] + (1ll*w*Pow(10, h[u])) % M) % M;
        down[v] = ((down[u]*10) % M + w) % M;
        h[v] = h[u] + 1;
        dfs_to_find_child(v, u, centroid);
    }
}

void deal(long long u)
{
    dfs_centroid(u);
    u = get_centroid(u);
    dd[u] = 1;h[u] = 0;num = 0;up[u] = down[u] = 0;
    child.clear();
    map<int, int> cnt;
    dfs_to_find_child(u, -1, u);
    vector<map<int, int> > be;
    be.resize(num+2);
    cnt[0]++;
    for(long long i = 0; i < child.size(); ++i)
    {
        long long v = child[i];
        if(v == u) continue;
        cnt[up[v]]++;
        be[belong[v]][up[v]]++;
    }
    for(long long i = 0; i < child.size(); ++i)
    {
        long long v = child[i];
        if(v == u) ans += cnt[0] - 1    ;
        else
        {
            long long val = (-down[v] + M) % M;
            val = (val * inverse(Pow(10, h[v]))) % M;
            ans += cnt[val] - be[belong[v]][val];
        }
    }
    for(long long i = 0; i < ke[u].size(); ++i)
        if(!dd[ke[u][i].F])
            deal(ke[u][i].F);
}

void work()
{
    init();
    deal(1);
    printf("%I64d", ans);
}

int main()
{
    //freopen(".inp", "r", stdin);
    setup();
    work();
}


#include <bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int md(ll a) { if (a >= mod) { return a%mod; } else { return a; } }
int add(int a, int b) { return md((ll)a+b); }
int sub(int a, int b) { return md(md((ll)a-b)%mod+mod); }
int mult(int a, int b) { return md((ll)a*b); }
int sq(int a) { return md((ll)a*a); }

bool compo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            compo[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
        while (n%i == 0) { n /= i; }
    }
    if (n) { ans *= (n-1)/n; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];

int down[MAX];
int up[MAX];

int comp[MAX];
int ccprev = 0;
int cc = 0;
unordered_map<int, int> maps[MAX];
unordered_map<int, int> comb;
vi nonzero;
vi all;
void dfs2(int st, int p) {
    // cout << "dfs: " << st << endl;
    all.pb(st);
    d[st] = d[p] + 1;
    if (d[st] != 0) { nonzero.pb(st); }
    comp[st] = cc;
    // if (!x) { ans += dist[solve(down[st], d[st])]; }
    maps[cc][up[st]]++;
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        // cout << "down of " << i.f << " is " << down[i.f] << endl;
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st);
    }
}

void process(int n) {
    ok[n] = false;
    all.clear();
    for (int i : nonzero) { d[i] = 0; }
    nonzero.clear();

    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n);
        cc++;
    }
    comb.clear();
    comb[0]++;
    FOR(i, ccprev, cc) {
        for (pii j : maps[i]) {
            comb[j.f] += j.s;
        }
    }
    ccprev = cc;

    // cout << "--process--"<< n << endl;
    // for (auto i : comb) { cout << i.f << " " << i.s << endl; }
    // cout << "-----------" << endl;
    for (int i : all) {
        ans += comb[solve(down[i], d[i])];
        // cout << i << " " << down[i] << " " << d[i] << " " << solve(down[i], d[i]) << endl;
        ans -= maps[comp[i]][solve(down[i], d[i])];
        if (up[i] == 0) { ans++; }
        // cout << "down.." << " " << i << " " << down[i] << endl;
        // cout << ans << endl;
    }

}
main() {
    freopen("why.txt", "r", stdin);
    scanf("%I64d", &n); scanf("%I64d", &mod);
    sieve(); phimod = phi(mod);
    cout << phimod << endl;
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%I64d %I64d %I64d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    // for (auto i : cents) { cout << i.f << " " << i.s << endl;}
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int add(int a, int b) { return ((ll)a+b)%mod; }
int sub(int a, int b) { return (((ll)a-b)%mod+mod)%mod; }
int mult(int a, int b) { return ((ll)a*b)%mod; }
int sq(int a) { return (ll)a*a%mod; }
bool compo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            compo[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

map<int, int> dist;
map<int, int> dist2;
int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];

int down[MAX];
int up[MAX];

int comp[MAX];
int cc = 0;
map<int, int> maps[MAX];
map<int, int> comb;
vi all;
void dfs2(int st, int p) {
    // cout << "dfs: " << st <<  endl;
    all.pb(st);
    d[st] = d[p] + 1;
    comp[st] = cc;
    // if (!x) { ans += dist[solve(down[st], d[st])]; }
    maps[cc][up[st]]++;
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        // cout << "down of " << i.f << " is " << down[i.f] << endl;
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st);
    }
}

void process(int n) {
    dist.clear();
    ok[n] = false;
    all.clear();
    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        maps[cc].clear();
        dfs2(i.f, n);
        cc++;
    }
    comb.clear();
    comb[0]++;
    F0R(i, cc) {
        for (pii j : maps[i]) {
            comb[j.f] += j.s;
        }
    }
    // cout << "--process--"<< n << endl;
    // for (auto i : comb) { cout << i.f << " " << i.s << endl; }
    // cout << "-----------" << endl;
    for (int i : all) {
        ans += comb[solve(down[i], d[i])];
        // cout << i << " " << down[i] << " " << d[i] << " " << solve(down[i], d[i]) << endl;
        ans -= maps[comp[i]][solve(down[i], d[i])];
        if (up[i] == 0) { ans++; }
        // cout << "down.." << " " << i << " " << down[i] << endl;
        // cout << ans << endl;
    }

}

int main() {
    scanf("%d", &n); scanf("%d", &mod);
    sieve(); phimod = phi(mod);
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%d %d %d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    // for (auto i : cents) { cout << i.f << " " << i.s << endl;}
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        if (i == 0 || cents[i].f != cents[i-1].f) {
            F0R(j, MAX) { maps[j].clear(); d[j] = 0; }
        }
        process(cents[i].s);
    }
    cout << ans << endl;
}
/*
15
1 2
3 2
4 2
2 5
5 6
6 7
5 8
8 9
9 10
10 11
10 12
9 13
13 14
13 15

*/


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int add(int a, int b) { return ((ll)a+b)%mod; }
int sub(int a, int b) { return (((ll)a-b)%mod+mod)%mod; }
int mult(int a, int b) { return ((ll)a*b)%mod; }
int sq(int a) { return (ll)a*a%mod; }
bool compo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            compo[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

map<int, int> dist;
map<int, int> dist2;
int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];

int down[MAX];
int up[MAX];

int comp[MAX];
int cc = 0;
map<int, int> maps[MAX];
map<int, int> comb;
vi all;
void dfs2(int st, int p) {
    // cout << "dfs: " << st << endl;
    all.pb(st);
    d[st] = d[p] + 1;
    comp[st] = cc;
    // if (!x) { ans += dist[solve(down[st], d[st])]; }
    maps[cc][up[st]]++;
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        // cout << "down of " << i.f << " is " << down[i.f] << endl;
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st);
    }
}

void process(int n) {
    dist.clear();
    ok[n] = false;
    all.clear();
    F0R(i, MAX) { maps[i].clear(); }

    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        maps[cc].clear();
        dfs2(i.f, n);
        cc++;
    }
    comb.clear();
    comb[0]++;
    F0R(i, cc) {
        for (pii j : maps[i]) {
            comb[j.f] += j.s;
        }
    }
    // cout << "--process--"<< n << endl;
    // for (auto i : comb) { cout << i.f << " " << i.s << endl; }
    // cout << "-----------" << endl;
    for (int i : all) {
        ans += comb[solve(down[i], d[i])];
        // cout << i << " " << down[i] << " " << d[i] << " " << solve(down[i], d[i]) << endl;
        ans -= maps[comp[i]][solve(down[i], d[i])];
        if (up[i] == 0) { ans++; }
        // cout << "down.." << " " << i << " " << down[i] << endl;
        // cout << ans << endl;
    }

}

int main() {
    scanf("%d", &n); scanf("%d", &mod);
    sieve(); phimod = phi(mod);
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%d %d %d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    // for (auto i : cents) { cout << i.f << " " << i.s << endl;}
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}
/*
15
1 2
3 2
4 2
2 5
5 6
6 7
5 8
8 9
9 10
10 11
10 12
9 13
13 14
13 15

*/


#include <bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int add(int a, int b) { return ((ll)a+b)%mod; }
int sub(int a, int b) { return (((ll)a-b)%mod+mod)%mod; }
int mult(int a, int b) { return ((ll)a*b)%mod; }
int sq(int a) { return ((ll)a*a)%mod; }
bool comp[MAX];
int iexpo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (comp[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            comp[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (comp[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
void invexpo() { F0R(i, MAX) { iexpo[i] = inv(expo(10, i)); } }
int solve(int dv, int h) {
    return mult(sub(0, dv), iexpo[h]);
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

unordered_map<int, int> dist;
int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];
int down[MAX];
int up[MAX];
vi seen;

void dfs2(int st, int p, int x) {
    if (x == 0) { seen.pb(st); d[st] = d[p] + 1; }
    if (!x) {
        // cout << "down: " << down[st] << endl;
        // cout << "searching for: " << solve(down[st], d[st]) << endl;
        ans += dist[solve(down[st], d[st])];
    }
    else { dist[up[st]]++; }
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st, x);
    }
}

void process(int n) {
    seen.clear();
    // for (auto i : dist) { cout << i.f << " " << i.s << endl; }
    // cout<<"process--"<<n<<endl;
    d[n] = 0;
    dist.clear();
    dist[0] = 1;
    ok[n] = false;
    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n, 0);
        dfs2(i.f, n, 1);
    }
    for (int i : seen) {
        if (down[i]%mod == 0) { ans--; }
        if (up[i]%mod == 0) { ans++; }
    }

    // for (auto i : dist) { cout << i.f << " " << i.s << endl; }
    // cout << "ans: " << ans << endl;
    // cout << "do the reverse!" << endl;
    dist.clear();
    dist[0] = 1;
    ok[n] = false;
    reverse(g2[n].begin(), g2[n].end());
    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n, 0);
        dfs2(i.f, n, 1);
    }

}

main() {
    dist.reserve(1024);
    dist.max_load_factor(0.25);
    scanf("%I64d", &n); scanf("%I64d", &mod);
    sieve(); phimod = phi(mod); invexpo();
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%I64d %I64d %I64d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    // cout<<"--------------------------"<<endl;
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int md(ll a) { if (a >= mod) { return a%mod; } else { return a; } }
int add(int a, int b) { return md((ll)a+b); }
int sub(int a, int b) { return md(md((ll)a-b)%mod+mod); }
int mult(int a, int b) { return md((ll)a*b); }
int sq(int a) { return md((ll)a*a); }

bool compo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            compo[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];

int down[MAX];
int up[MAX];

int comp[MAX];
int ccprev = 0;
int cc = 0;
unordered_map<int, int> maps[MAX];
unordered_map<int, int> comb;
vi nonzero;
vi all;
void dfs2(int st, int p) {
    // cout << "dfs: " << st << endl;
    all.pb(st);
    d[st] = d[p] + 1;
    if (d[st] != 0) { nonzero.pb(st); }
    comp[st] = cc;
    // if (!x) { ans += dist[solve(down[st], d[st])]; }
    maps[cc][up[st]]++;
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        // cout << "down of " << i.f << " is " << down[i.f] << endl;
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st);
    }
}

void process(int n) {
    ok[n] = false;
    all.clear();
    for (int i : nonzero) { d[i] = 0; }
    nonzero.clear();

    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n);
        cc++;
    }
    comb.clear();
    comb[0]++;
    FOR(i, ccprev, cc) {
        for (pii j : maps[i]) {
            comb[j.f] += j.s;
        }
    }
    ccprev = cc;

    // cout << "--process--"<< n << endl;
    // for (auto i : comb) { cout << i.f << " " << i.s << endl; }
    // cout << "-----------" << endl;
    for (int i : all) {
        ans += comb[solve(down[i], d[i])];
        // cout << i << " " << down[i] << " " << d[i] << " " << solve(down[i], d[i]) << endl;
        ans -= maps[comp[i]][solve(down[i], d[i])];
        if (up[i] == 0) { ans++; }
        // cout << "down.." << " " << i << " " << down[i] << endl;
        // cout << ans << endl;
    }

}
main() {
    scanf("%I64d", &n); scanf("%I64d", &mod);
    sieve(); phimod = phi(mod);
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%I64d %I64d %I64d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    // for (auto i : cents) { cout << i.f << " " << i.s << endl;}
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;

#define int long long
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int md(ll a) { if (a > mod) { return a%mod; } else { return a; } }
int add(int a, int b) { return md((ll)a+b); }
int sub(int a, int b) { return md(md((ll)a-b)%mod+mod); }
int mult(int a, int b) { return md((ll)a*b); }
int sq(int a) { return md((ll)a*a); }
bool compo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            compo[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];

int down[MAX];
int up[MAX];

int comp[MAX];
int ccprev = 0;
int cc = 0;
unordered_map<int, int> maps[MAX];
unordered_map<int, int> comb;
vi nonzero;
vi all;
void dfs2(int st, int p) {
    // cout << "dfs: " << st << endl;
    all.pb(st);
    d[st] = d[p] + 1;
    if (d[st] != 0) { nonzero.pb(st); }
    comp[st] = cc;
    // if (!x) { ans += dist[solve(down[st], d[st])]; }
    maps[cc][up[st]]++;
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        // cout << "down of " << i.f << " is " << down[i.f] << endl;
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st);
    }
}

void process(int n) {
    ok[n] = false;
    all.clear();
    for (int i : nonzero) { d[i] = 0; }
    nonzero.clear();

    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n);
        cc++;
    }
    comb.clear();
    comb[0]++;
    FOR(i, ccprev, cc) {
        for (pii j : maps[i]) {
            comb[j.f] += j.s;
        }
    }
    ccprev = cc;

    // cout << "--process--"<< n << endl;
    // for (auto i : comb) { cout << i.f << " " << i.s << endl; }
    // cout << "-----------" << endl;
    for (int i : all) {
        ans += comb[solve(down[i], d[i])];
        // cout << i << " " << down[i] << " " << d[i] << " " << solve(down[i], d[i]) << endl;
        ans -= maps[comp[i]][solve(down[i], d[i])];
        if (up[i] == 0) { ans++; }
        // cout << "down.." << " " << i << " " << down[i] << endl;
        // cout << ans << endl;
    }

}
main() {
    scanf("%I64d", &n); scanf("%I64d", &mod);
    sieve(); phimod = phi(mod);
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%I64d %I64d %I64d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    // for (auto i : cents) { cout << i.f << " " << i.s << endl;}
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int add(int a, int b) { return ((ll)a+b)%mod; }
int sub(int a, int b) { return (((ll)a-b)%mod+mod)%mod; }
int mult(int a, int b) { return ((ll)a*b)%mod; }
int sq(int a) { return (ll)a*a%mod; }
bool compo[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            compo[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (compo[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

map<int, int> dist;
map<int, int> dist2;
int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];

int down[MAX];
int up[MAX];

int comp[MAX];
int cc = 0;
map<int, int> maps[MAX];
map<int, int> comb;
vi all;
void dfs2(int st, int p) {
    // cout << "dfs: " << st << endl;
    all.pb(st);
    d[st] = d[p] + 1;
    comp[st] = cc;
    // if (!x) { ans += dist[solve(down[st], d[st])]; }
    maps[cc][up[st]]++;
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        // cout << "down of " << i.f << " is " << down[i.f] << endl;
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st);
    }
}

void process(int n) {
    dist.clear();
    ok[n] = false;
    all.clear();
    F0R(i, MAX) { maps[i].clear(); d[i] = 0; }

    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        maps[cc].clear();
        dfs2(i.f, n);
        cc++;
    }
    comb.clear();
    comb[0]++;
    F0R(i, cc) {
        for (pii j : maps[i]) {
            comb[j.f] += j.s;
        }
    }
    // cout << "--process--"<< n << endl;
    // for (auto i : comb) { cout << i.f << " " << i.s << endl; }
    // cout << "-----------" << endl;
    for (int i : all) {
        ans += comb[solve(down[i], d[i])];
        // cout << i << " " << down[i] << " " << d[i] << " " << solve(down[i], d[i]) << endl;
        ans -= maps[comp[i]][solve(down[i], d[i])];
        if (up[i] == 0) { ans++; }
        // cout << "down.." << " " << i << " " << down[i] << endl;
        // cout << ans << endl;
    }

}

int main() {
    scanf("%d", &n); scanf("%d", &mod);
    sieve(); phimod = phi(mod);
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%d %d %d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    // for (auto i : cents) { cout << i.f << " " << i.s << endl;}
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}
/*
15
1 2
3 2
4 2
2 5
5 6
6 7
5 8
8 9
9 10
10 11
10 12
9 13
13 14
13 15

*/


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define f first
#define s second
#define pb push_back
#define mp make_pair

#define FOR(i, a, b) for (int i=a; i<b; i++)
#define F0R(i, a) FOR(i, 0, a)

const int MAX = 100005;
const int MOD = 1000000007;

int mod, phimod;
int add(int a, int b) { return ((ll)a+b)%mod; }
int sub(int a, int b) { return (((ll)a-b)%mod+mod)%mod; }
int mult(int a, int b) { return ((ll)a*b)%mod; }
int sq(int a) { return ((ll)a*a)%mod; }
bool comp[MAX];
void sieve() {
    FOR(i, 2, MAX) {
        if (comp[i]) { continue; }
        for (int j=2*i; j<MAX; j+=i) {
            comp[j] = true;
        }
    }
}

int phi(int n) {
    bool p = true;
    int ans = n;
    FOR(i, 2, MAX) {
        if (comp[i]) { continue; }
        if (n%i == 0) { ans /= i; ans *= (i-1); p = false; }
    }
    if (p) { return n-1; }
    return ans;
}

int expo(int a, int b) {
    if (b == 0) { return 1; }
    if (b%2) { return mult(a, sq(expo(a, b/2))); }
    else { return sq(expo(a, b/2)); }
}
int inv(int a) { return expo(a, phimod-1); }
int solve(int dv, int h) {
    return mult(sub(0, dv), inv(expo(10, h)));
}

vi g[MAX];
int n;
bool ok[MAX];
int sztot = 0;
int sz[MAX];

void dfs(int st, int p) {
    sz[st] = 1; sztot++;
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        dfs(i, st);
        sz[st] += sz[i];
    }
}

int cent(int st, int p) {
    for (int i : g[st]) {
        if (i == p || !ok[i]) { continue; }
        if (sz[i] > sztot / 2) { return cent(i, st); }
    }
    return st;
}

int par[MAX];
int dcent[MAX];
void decomp(int st, int p) {
    par[st] = p; dcent[st] = dcent[p] + 1;
    ok[st] = false;
    for (int i : g[st]) {
        if (!ok[i]) { continue; }
        sztot = 0;
        dfs(i, -1);
        int c = cent(i, -1);
        decomp(c, st);
    }
}

map<int, int> dist;
int ans = 0;
int L = 2;
vector<pii> g2[MAX];
int d[MAX];
int down[MAX];
int up[MAX];
vi seen;

void dfs2(int st, int p, int x) {
    if (x == 0) { seen.pb(st); d[st] = d[p] + 1; }
    if (!x) {
        // cout << "down: " << down[st] << endl;
        // cout << "searching for: " << solve(down[st], d[st]) << endl;
        ans += dist[solve(down[st], d[st])];
    }
    else { dist[up[st]]++; }
    for (pii i : g2[st]) {
        if (i.f == p || !ok[i.f]) { continue; }
        down[i.f] = add(mult(down[st], 10), i.s);
        up[i.f] = add(up[st], mult(i.s, expo(10, d[st])));
        dfs2(i.f, st, x);
    }
}

void process(int n) {
    seen.clear();
    // for (auto i : dist) { cout << i.f << " " << i.s << endl; }
    // cout<<"process--"<<n<<endl;
    d[n] = 0;
    dist.clear();
    dist[0] = 1;
    ok[n] = false;
    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n, 0);
        dfs2(i.f, n, 1);
    }
    for (int i : seen) {
        if (down[i]%mod == 0) { ans--; }
        if (up[i]%mod == 0) { ans++; }
    }

    // for (auto i : dist) { cout << i.f << " " << i.s << endl; }
    // cout << "ans: " << ans << endl;
    // cout << "do the reverse!" << endl;
    dist.clear();
    dist[0] = 1;
    ok[n] = false;
    reverse(g2[n].begin(), g2[n].end());
    for (pii i : g2[n]) {
        if (!ok[i.f]) { continue; }
        down[i.f] = i.s%mod;
        up[i.f] = i.s%mod;
        dfs2(i.f, n, 0);
        dfs2(i.f, n, 1);
    }

}

int main() {
    scanf("%d", &n); scanf("%d", &mod);
    sieve(); phimod = phi(mod);
    F0R(i, MAX) { ok[i] = true; }
    F0R(i, n-1) {
        int u, v, w; scanf("%d %d %d", &u, &v, &w);
        g[u].pb(v); g[v].pb(u);
        g2[u].pb({v, w}); g2[v].pb({u, w});
    }
    // cout<<"--------------------------"<<endl;
    dfs(0, -1);
    int r = cent(0, -1);
    decomp(r, -1);
    F0R(i, MAX) { ok[i] = true; }
    //remember to reset dist appropritaely
    vector<pii> cents;
    FOR(i, 0, n) { cents.pb({dcent[i], i}); }
    sort(cents.begin(), cents.end());
    F0R(i, n) {
        process(cents[i].s);
    }
    cout << ans << endl;
}
/*
15
1 2
3 2
4 2
2 5
5 6
6 7
5 8
8 9
9 10
10 11
10 12
9 13
13 14
13 15

*/