#include <bits/stdc++.h>
using namespace std;
#define int long double
#define PI (long double) acos(-1)
int x1, y1, r1;
int x2, y2, r2;

int pow(int x) { return x * x; }
int dist2(int x1, int y1, int x2, int y2) {
    return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
}

long double dist(int x1, int y1, int x2, int y2) {
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
signed main() {
    cin>>x1>>y1>>r1;
    cin>>x2>>y2>>r2;

    int cd = dist2(x1, y1, x2, y2);
    if(pow(r1 + r2) <= cd) return puts("0");
    if(cd <= pow(r1 - r2)) {
        return printf("%.15Lf",  pow(min(r1, r2)) * PI) % 1;
    }
    long double t1 = acos((-pow(r2) + cd + pow(r1)) / (2 * (long double) sqrt(cd) * r1));
    long double t2 = acos((-pow(r1) + cd + pow(r2)) / (2 * (long double) sqrt(cd) * r2));
    if (t1 < 1e-8)
        return printf("%.15Lf", pow(r2) * t2) % 1;
    if (t2 < 1e-8)
        return printf("%.15Lf", pow(r1) * t1) % 1;
    printf("%.15Lf", pow(r1) * (t1 - cos(t1) * sin(t1)) + pow(r2) * (t2 - cos(t2) * sin(t2)));
	return 0;
}


#include <bits/stdc++.h>
#define PI acos(-1)
using namespace std;
const double eps = 1e-15;

inline int diff(double lhs, double rhs) {
    if (lhs - eps < rhs && rhs < lhs + eps) return 0;
    return (lhs < rhs) ? -1 : 1;
}

inline bool is_between(double check, double a, double b) {
    if (a < b)
        return (a - eps < check && check < b + eps);
    else
        return (b - eps < check && check < a + eps);
}

struct Point {
    double x, y;
    bool operator==(const Point& rhs) const {
        return diff(x, rhs.x) == 0 && diff(y, rhs.y) == 0;
    }
    Point operator+(const Point& rhs) const {
        return Point{ x + rhs.x, y + rhs.y };
    }
    Point operator-(const Point& rhs) const {
        return Point{ x - rhs.x, y - rhs.y };
    }
    Point operator*(double t) const {
        return Point{ x * t, y * t };
    }
};

struct Circle {
    Point center;
    double r;
};

struct Line {
    Point pos, dir;
};

inline double inner(const Point& a, const Point& b) {
    return a.x * b.x + a.y * b.y;
}

inline double outer(const Point& a, const Point& b) {
    return a.x * b.y - a.y * b.x;
}

inline int ccw_line(const Line& line, const Point& point) {
    return diff(outer(line.dir, point - line.pos), 0);
}

inline int ccw(const Point& a, const Point& b, const Point& c) {
    return diff(outer(b - a, c - a), 0);
}

inline double dist(const Point& a, const Point& b) {
    return sqrt(inner(a - b, a - b));
}

inline double dist2(const Point &a, const Point &b) {
    return inner(a - b, a - b);
}

inline double dist(const Line& line, const Point& point, bool segment = false) {
    double c1 = inner(point - line.pos, line.dir);
    if (segment && diff(c1, 0) <= 0) return dist(line.pos, point);
    double c2 = inner(line.dir, line.dir);
    if (segment && diff(c2, c1) <= 0) return dist(line.pos + line.dir, point);
    return dist(line.pos + line.dir * (c1 / c2), point);
}

bool get_cross(const Line& a, const Line& b, Point& ret) {
    double mdet = outer(b.dir, a.dir);
    if (diff(mdet, 0) == 0) return false;
    double t2 = outer(a.dir, b.pos - a.pos) / mdet;
    ret = b.pos + b.dir * t2;
    return true;
}

bool get_segment_cross(const Line& a, const Line& b, Point& ret) {
    double mdet = outer(b.dir, a.dir);
    if (diff(mdet, 0) == 0) return false;
    double t1 = -outer(b.pos - a.pos, b.dir) / mdet;
    double t2 = outer(a.dir, b.pos - a.pos) / mdet;
    if (!is_between(t1, 0, 1) || !is_between(t2, 0, 1)) return false;
    ret = b.pos + b.dir * t2;
    return true;
}

Point inner_center(const Point &a, const Point &b, const Point &c) {
    double wa = dist(b, c), wb = dist(c, a), wc = dist(a, b);
    double w = wa + wb + wc;
    return Point{ (wa * a.x + wb * b.x + wc * c.x) / w, (wa * a.y + wb * b.y + wc * c.y) / w };
}

Point outer_center(const Point &a, const Point &b, const Point &c) {
    Point d1 = b - a, d2 = c - a;
    double area = outer(d1, d2);
    double dx = d1.x * d1.x * d2.y - d2.x * d2.x * d1.y
        + d1.y * d2.y * (d1.y - d2.y);
    double dy = d1.y * d1.y * d2.x - d2.y * d2.y * d1.x
        + d1.x * d2.x * (d1.x - d2.y);
    return Point{ a.x + dx / area / 2.0, a.y - dy / area / 2.0 };
}

vector<Point> circle_line(const Circle& circle, const Line& line) {
    vector<Point> result;
    double a = 2 * inner(line.dir, line.dir);
    double b = 2 * (line.dir.x * (line.pos.x - circle.center.x)
        + line.dir.y * (line.pos.y - circle.center.y));
    double c = inner(line.pos - circle.center, line.pos - circle.center)
        - circle.r * circle.r;
    double det = b * b - 2 * a * c;
    int pred = diff(det, 0);
    if (pred == 0)
        result.push_back(line.pos + line.dir * (-b / a));
    else if (pred > 0) {
        det = sqrt(det);
        result.push_back(line.pos + line.dir * ((-b + det) / a));
        result.push_back(line.pos + line.dir * ((-b - det) / a));
    }
    return result;
}

vector<Point> circle_circle(const Circle& a, const Circle& b) {
    vector<Point> result;
    double aa = a.center.x * a.center.x + a.center.y * a.center.y - a.r * a.r;
    double bb = b.center.x * b.center.x + b.center.y * b.center.y - b.r * b.r;
    double tmp = (bb - aa) / 2.0;
    Point cdiff = b.center - a.center;
    if (diff(cdiff.x, 0) == 0) {
        if (diff(cdiff.y, 0) == 0) {
            return result;
        }
        return circle_line(a, Line{ Point{ 0, tmp / cdiff.y }, Point{ 1, 0 } });
    }
    return circle_line(a,
        Line{ Point{ tmp / cdiff.x, 0 }, Point{ -cdiff.y, cdiff.x } });
}

Point ret;
Circle a, b;

double cs(double r, double h) {
    return r * r * h;
}

double ts(double a, double b) {
    return sqrt(a + b / 2) * sqrt(a - b / 2) * b / 2;
}

signed main() {
    cin>>a.center.x>>a.center.y>>a.r;
    cin>>b.center.x>>b.center.y>>b.r;
    int pred = diff(dist(a.center, b.center), a.r + b.r);
    if (pred >= 0) return puts("0");
    auto r = circle_circle(a, b);
    double cc = dist(a.center, b.center);
    if(cc <= max(a.r - b.r, b.r - a.r) || !r.size())
        return printf("%.15f\n", min(a.r, b.r) * min(a.r, b.r) * PI) % 1;
    auto p = r.front(), q = r.back();
    double d = sqrt(abs(-cc + a.r - b.r)) * sqrt(abs(-cc - a.r + b.r)) * sqrt(-cc + a.r + b.r) * sqrt(cc + a.r + b.r) / cc;
    double sa = asin(d / 2 / a.r);
    double sb = asin(d / 2 / b.r);
    if (a.center.x == 44721) printf("1 ");
    if(get_segment_cross(Line{a.center, b.center - a.center}, Line{p, q - p}, ret)){
        return printf("%.15f\n", cs(a.r, sa) + cs(b.r, sb) - ts(a.r, d) - ts(b.r, d)) % 1;
    }
    if (a.center.x == 44721) printf("2 ");
    if(dist(Line{p, q - p}, a.center, true) < dist(Line{p, q - p}, b.center, true))
        return printf("%.15f\n", cs(a.r, PI - sa) + cs(b.r, sb) + ts(a.r, d) - ts(b.r, d)) % 1;
    if (a.center.x == 44721) printf("3 ");
    return printf("%.15f\n", cs(a.r, sa) + cs(b.r, PI - sb) - ts(a.r, d) + ts(b.r, d)) % 1;
}


#include <bits/stdc++.h>
using namespace std;
#define int long double
#define PI (long double) acos(-1)
int x1, y1, r1;
int x2, y2, r2;

int pow(int x) { return x * x; }
int dist2(int x1, int y1, int x2, int y2) {
    return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
}

long double dist(int x1, int y1, int x2, int y2) {
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
signed main() {
    cin>>x1>>y1>>r1;
    cin>>x2>>y2>>r2;

    int cd = dist2(x1, y1, x2, y2);
    if(pow(r1 + r2) <= cd) return puts("0");
    if(cd <= pow(r1 - r2)) {
        return printf("%.15Lf",  pow(min(r1, r2)) * PI) % 1;
    }
    long double t1 = acos((-pow(r2) + cd + pow(r1)) / (2 * (long double) sqrt(cd) * r1));
    long double t2 = acos((-pow(r1) + cd + pow(r2)) / (2 * (long double) sqrt(cd) * r2));
    printf("%.15Lf", pow(r1) * (t1 - cos(t1) * sin(t1)) + pow(r2) * (t2 - cos(t2) * sin(t2)));
	return 0;
}


#include <bits/stdc++.h>
#define PI acos(-1)
using namespace std;
const double eps = 1e-9;

inline int diff(double lhs, double rhs) {
    if (lhs - eps < rhs && rhs < lhs + eps) return 0;
    return (lhs < rhs) ? -1 : 1;
}

inline bool is_between(double check, double a, double b) {
    if (a < b)
        return (a - eps < check && check < b + eps);
    else
        return (b - eps < check && check < a + eps);
}

struct Point {
    double x, y;
    bool operator==(const Point& rhs) const {
        return diff(x, rhs.x) == 0 && diff(y, rhs.y) == 0;
    }
    Point operator+(const Point& rhs) const {
        return Point{ x + rhs.x, y + rhs.y };
    }
    Point operator-(const Point& rhs) const {
        return Point{ x - rhs.x, y - rhs.y };
    }
    Point operator*(double t) const {
        return Point{ x * t, y * t };
    }
};

struct Circle {
    Point center;
    double r;
};

struct Line {
    Point pos, dir;
};

inline double inner(const Point& a, const Point& b) {
    return a.x * b.x + a.y * b.y;
}

inline double outer(const Point& a, const Point& b) {
    return a.x * b.y - a.y * b.x;
}

inline int ccw_line(const Line& line, const Point& point) {
    return diff(outer(line.dir, point - line.pos), 0);
}

inline int ccw(const Point& a, const Point& b, const Point& c) {
    return diff(outer(b - a, c - a), 0);
}

inline double dist(const Point& a, const Point& b) {
    return sqrt(inner(a - b, a - b));
}

inline double dist2(const Point &a, const Point &b) {
    return inner(a - b, a - b);
}

inline double dist(const Line& line, const Point& point, bool segment = false) {
    double c1 = inner(point - line.pos, line.dir);
    if (segment && diff(c1, 0) <= 0) return dist(line.pos, point);
    double c2 = inner(line.dir, line.dir);
    if (segment && diff(c2, c1) <= 0) return dist(line.pos + line.dir, point);
    return dist(line.pos + line.dir * (c1 / c2), point);
}

bool get_cross(const Line& a, const Line& b, Point& ret) {
    double mdet = outer(b.dir, a.dir);
    if (diff(mdet, 0) == 0) return false;
    double t2 = outer(a.dir, b.pos - a.pos) / mdet;
    ret = b.pos + b.dir * t2;
    return true;
}

bool get_segment_cross(const Line& a, const Line& b, Point& ret) {
    double mdet = outer(b.dir, a.dir);
    if (diff(mdet, 0) == 0) return false;
    double t1 = -outer(b.pos - a.pos, b.dir) / mdet;
    double t2 = outer(a.dir, b.pos - a.pos) / mdet;
    if (!is_between(t1, 0, 1) || !is_between(t2, 0, 1)) return false;
    ret = b.pos + b.dir * t2;
    return true;
}

Point inner_center(const Point &a, const Point &b, const Point &c) {
    double wa = dist(b, c), wb = dist(c, a), wc = dist(a, b);
    double w = wa + wb + wc;
    return Point{ (wa * a.x + wb * b.x + wc * c.x) / w, (wa * a.y + wb * b.y + wc * c.y) / w };
}

Point outer_center(const Point &a, const Point &b, const Point &c) {
    Point d1 = b - a, d2 = c - a;
    double area = outer(d1, d2);
    double dx = d1.x * d1.x * d2.y - d2.x * d2.x * d1.y
        + d1.y * d2.y * (d1.y - d2.y);
    double dy = d1.y * d1.y * d2.x - d2.y * d2.y * d1.x
        + d1.x * d2.x * (d1.x - d2.y);
    return Point{ a.x + dx / area / 2.0, a.y - dy / area / 2.0 };
}

vector<Point> circle_line(const Circle& circle, const Line& line) {
    vector<Point> result;
    double a = 2 * inner(line.dir, line.dir);
    double b = 2 * (line.dir.x * (line.pos.x - circle.center.x)
        + line.dir.y * (line.pos.y - circle.center.y));
    double c = inner(line.pos - circle.center, line.pos - circle.center)
        - circle.r * circle.r;
    double det = b * b - 2 * a * c;
    int pred = diff(det, 0);
    if (pred == 0)
        result.push_back(line.pos + line.dir * (-b / a));
    else if (pred > 0) {
        det = sqrt(det);
        result.push_back(line.pos + line.dir * ((-b + det) / a));
        result.push_back(line.pos + line.dir * ((-b - det) / a));
    }
    return result;
}

vector<Point> circle_circle(const Circle& a, const Circle& b) {
    vector<Point> result;
    int pred = diff(dist(a.center, b.center), a.r + b.r);
    if (pred > 0) return result;
    if (pred == 0) {
        return result;
    }
    double aa = a.center.x * a.center.x + a.center.y * a.center.y - a.r * a.r;
    double bb = b.center.x * b.center.x + b.center.y * b.center.y - b.r * b.r;
    double tmp = (bb - aa) / 2.0;
    Point cdiff = b.center - a.center;
    if (diff(cdiff.x, 0) == 0) {
        if (diff(cdiff.y, 0) == 0) {
            result.push_back(Point {0, 0});
            return result;
        }
        return circle_line(a, Line{ Point{ 0, tmp / cdiff.y }, Point{ 1, 0 } });
    }
    return circle_line(a,
        Line{ Point{ tmp / cdiff.x, 0 }, Point{ -cdiff.y, cdiff.x } });
}

Point ret;
Circle a, b;
int main() {
    cin>>a.center.x>>a.center.y>>a.r;
    cin>>b.center.x>>b.center.y>>b.r;
    auto r = circle_circle(a, b);
    int rs = (int) r.size();
    if(rs == 0) return puts("0");
    if(rs == 1) return printf("%.15f\n", min(a.r, b.r) * min(a.r, b.r) * PI) % 1;
    auto p = r.front(), q = r.back();
    double d = dist(p, q);
    double sa = asin(d / 2 / a.r) * 2;
    double sb = asin(d / 2 / b.r) * 2;
    if(get_segment_cross(Line{a.center, b.center}, Line{p, q}, ret)) {
        return printf("%.15f\n", a.r * a.r * sa / 2 + b.r * b.r * sb / 2 - a.r * a.r * sin(sa) / 2 - b.r * b.r * sin(sb) / 2) % 1;
    }
    if(dist(Line{p, q}, a.center, true) < dist(Line{p, q}, b.center, true))
        return printf("%.15f\n", a.r * a.r * (PI - sa / 2) + b.r * b.r * sb / 2 - a.r * a.r * sin(sa) / 2 - b.r * b.r * sin(sb) / 2) % 1;
    return printf("%.15f\n", a.r * a.r * sa / 2 + b.r * b.r * (PI - sb / 2) - a.r * a.r * sin(sa) / 2 - b.r * b.r * sin(sb) / 2) % 1;
}


#include <bits/stdc++.h>
#define PI acos(-1)
using namespace std;
const double eps = 1e-15;

inline int diff(double lhs, double rhs) {
    if (lhs - eps < rhs && rhs < lhs + eps) return 0;
    return (lhs < rhs) ? -1 : 1;
}

inline bool is_between(double check, double a, double b) {
    if (a < b)
        return (a - eps < check && check < b + eps);
    else
        return (b - eps < check && check < a + eps);
}

struct Point {
    double x, y;
    bool operator==(const Point& rhs) const {
        return diff(x, rhs.x) == 0 && diff(y, rhs.y) == 0;
    }
    Point operator+(const Point& rhs) const {
        return Point{ x + rhs.x, y + rhs.y };
    }
    Point operator-(const Point& rhs) const {
        return Point{ x - rhs.x, y - rhs.y };
    }
    Point operator*(double t) const {
        return Point{ x * t, y * t };
    }
};

struct Circle {
    Point center;
    double r;
};

struct Line {
    Point pos, dir;
};

inline double inner(const Point& a, const Point& b) {
    return a.x * b.x + a.y * b.y;
}

inline double outer(const Point& a, const Point& b) {
    return a.x * b.y - a.y * b.x;
}

inline int ccw_line(const Line& line, const Point& point) {
    return diff(outer(line.dir, point - line.pos), 0);
}

inline int ccw(const Point& a, const Point& b, const Point& c) {
    return diff(outer(b - a, c - a), 0);
}

inline double dist(const Point& a, const Point& b) {
    return sqrt(inner(a - b, a - b));
}

inline double dist2(const Point &a, const Point &b) {
    return inner(a - b, a - b);
}

inline double dist(const Line& line, const Point& point, bool segment = false) {
    double c1 = inner(point - line.pos, line.dir);
    if (segment && diff(c1, 0) <= 0) return dist(line.pos, point);
    double c2 = inner(line.dir, line.dir);
    if (segment && diff(c2, c1) <= 0) return dist(line.pos + line.dir, point);
    return dist(line.pos + line.dir * (c1 / c2), point);
}

bool get_cross(const Line& a, const Line& b, Point& ret) {
    double mdet = outer(b.dir, a.dir);
    if (diff(mdet, 0) == 0) return false;
    double t2 = outer(a.dir, b.pos - a.pos) / mdet;
    ret = b.pos + b.dir * t2;
    return true;
}

bool get_segment_cross(const Line& a, const Line& b, Point& ret) {
    double mdet = outer(b.dir, a.dir);
    if (diff(mdet, 0) == 0) return false;
    double t1 = -outer(b.pos - a.pos, b.dir) / mdet;
    double t2 = outer(a.dir, b.pos - a.pos) / mdet;
    if (!is_between(t1, 0, 1) || !is_between(t2, 0, 1)) return false;
    ret = b.pos + b.dir * t2;
    return true;
}

Point inner_center(const Point &a, const Point &b, const Point &c) {
    double wa = dist(b, c), wb = dist(c, a), wc = dist(a, b);
    double w = wa + wb + wc;
    return Point{ (wa * a.x + wb * b.x + wc * c.x) / w, (wa * a.y + wb * b.y + wc * c.y) / w };
}

Point outer_center(const Point &a, const Point &b, const Point &c) {
    Point d1 = b - a, d2 = c - a;
    double area = outer(d1, d2);
    double dx = d1.x * d1.x * d2.y - d2.x * d2.x * d1.y
        + d1.y * d2.y * (d1.y - d2.y);
    double dy = d1.y * d1.y * d2.x - d2.y * d2.y * d1.x
        + d1.x * d2.x * (d1.x - d2.y);
    return Point{ a.x + dx / area / 2.0, a.y - dy / area / 2.0 };
}

vector<Point> circle_line(const Circle& circle, const Line& line) {
    vector<Point> result;
    double a = 2 * inner(line.dir, line.dir);
    double b = 2 * (line.dir.x * (line.pos.x - circle.center.x)
        + line.dir.y * (line.pos.y - circle.center.y));
    double c = inner(line.pos - circle.center, line.pos - circle.center)
        - circle.r * circle.r;
    double det = b * b - 2 * a * c;
    int pred = diff(det, 0);
    if (pred == 0)
        result.push_back(line.pos + line.dir * (-b / a));
    else if (pred > 0) {
        det = sqrt(det);
        result.push_back(line.pos + line.dir * ((-b + det) / a));
        result.push_back(line.pos + line.dir * ((-b - det) / a));
    }
    return result;
}

vector<Point> circle_circle(const Circle& a, const Circle& b) {
    vector<Point> result;
    double aa = a.center.x * a.center.x + a.center.y * a.center.y - a.r * a.r;
    double bb = b.center.x * b.center.x + b.center.y * b.center.y - b.r * b.r;
    double tmp = (bb - aa) / 2.0;
    Point cdiff = b.center - a.center;
    if (diff(cdiff.x, 0) == 0) {
        if (diff(cdiff.y, 0) == 0) {
            return result;
        }
        return circle_line(a, Line{ Point{ 0, tmp / cdiff.y }, Point{ 1, 0 } });
    }
    return circle_line(a,
        Line{ Point{ tmp / cdiff.x, 0 }, Point{ -cdiff.y, cdiff.x } });
}

Point ret;
Circle a, b;

double cs(double r, double h) {
    return r * r * h;
}

double ts(double a, double b) {
    return sqrt(a + b / 2) * sqrt(a - b / 2) * b / 2;
}

signed main() {
    cin>>a.center.x>>a.center.y>>a.r;
    cin>>b.center.x>>b.center.y>>b.r;
    int pred = diff(dist(a.center, b.center), a.r + b.r);
    if (pred >= 0) return puts("0");
    auto r = circle_circle(a, b);
    double cc = dist(a.center, b.center);
    if (a.center.x == 44721) printf("%.15f %d\n", cc, (int) r.size());
    if(cc <= max(a.r - b.r, b.r - a.r) || !r.size())
        return printf("%.15f\n", min(a.r, b.r) * min(a.r, b.r) * PI) % 1;
    auto p = r.front(), q = r.back();
    double d = sqrt(abs(-cc + a.r - b.r)) * sqrt(abs(-cc - a.r + b.r)) * sqrt(-cc + a.r + b.r) * sqrt(cc + a.r + b.r) / cc;
    double sa = asin(d / 2 / a.r);
    double sb = asin(d / 2 / b.r);
    if (a.center.x == 44721) printf("%.15f %d\n", cc, (int) r.size());
    if(get_segment_cross(Line{a.center, b.center - a.center}, Line{p, q - p}, ret)){
        return printf("%.15f\n", cs(a.r, sa) + cs(b.r, sb) - ts(a.r, d) - ts(b.r, d)) % 1;
    }
    if (a.center.x == 44721) printf("%.15f %d\n", cc, (int) r.size());
    if(dist(Line{p, q - p}, a.center, true) < dist(Line{p, q - p}, b.center, true))
        return printf("%.15f\n", cs(a.r, PI - sa) + cs(b.r, sb) + ts(a.r, d) - ts(b.r, d)) % 1;
    if (a.center.x == 44721) printf("%.15f %d\n", cc, (int) r.size());
    return printf("%.15f\n", cs(a.r, sa) + cs(b.r, PI - sb) - ts(a.r, d) + ts(b.r, d)) % 1;
}


#include <bits/stdc++.h>
using namespace std;
#define int long double
#define PI (int) acos(-1)
int x1, y1, r1;
int x2, y2, r2;
const long double eps = 1e-15;

long double dist(int x1, int y1, int x2, int y2) {
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
signed main() {
    cin>>x1>>y1>>r1;
    cin>>x2>>y2>>r2;
    int r = 1;
    x1 /= r;
    x2 /= r;
    y1 /= r;
    y2 /= r;
    r1 /= r;
    r2 /= r;

    long double cd = dist(x1, y1, x2, y2);
    if(r1 + r2 - eps <= cd) return puts("0");
    if(cd + r2 - eps  <= r1) {
        return printf("%.15Lf",  r2 * r2 * PI * r * r) % 1;
    }
    if(cd + r1 - eps  <= r2) {
        return printf("%.15Lf",  r1 * r1 * PI * r * r) % 1;
    }
    long double s = (cd + r1 + r2) / 2;
    long double ts = sqrt(s) * sqrt(s - cd) * sqrt(s - r1) * sqrt(s - r2);
    long double t1 = (-r2 * r2 + cd * cd + r1 * r1) / 2 / cd / r1;
    long double t2 = (-r1 * r1 + cd * cd + r2 * r2) / 2 / cd / r2;
    return printf("%.15Lf", (r1 * r1 * acos(t1) + r2 * r2 * acos(t2) - ts * 2) * r * r) % 1;
}


#include<bits/stdc++.h>
#include <unordered_map>
using std::unordered_map;
int main(){
typedef void(*FuncA)(int, int);
typedef void(*FuncB)(int, int, int, int, int, int, int);
typedef unordered_map<int, int>::iterator IT;
static long long ans = 0;
static int n, M, *ei, *mul, *inv;
static unordered_map<int, int> **up;
static int a, b, c, d, i, j, k, l, t;
static struct Edge{ int l, t, v; } *e;
static FuncB funcB = [](int s, int p, int r, int rp, int v, int sum, int h){
	a = ((M - sum) * inv[h]) % M; b = ((a - (v % M) + M) * inv[0]) % M;
	IT t1 = up[rp]->find(a), t2 = up[r]->find(b);
	ans += (t1 != up[rp]->end() ? t1->second : 0)
		- (t2 != up[r]->end() ? t2->second : 0);
	int j;
	for(j = ei[s]; j != -1; j = e[j].l) if(e[j].t != p)
		funcB(e[j].t, s, r, rp, v, (sum * mul[0] + e[j].v) % M, h + 1);
};
static FuncA funcA = [](int s, int p){
	int i;
	for(i = ei[s]; i != -1; i = e[i].l)
		if(e[i].t != p) funcA(e[i].t, s);
	up[s] = new unordered_map<int, int>;
	for(i = ei[s], (*up[s])[0] = 1; i != -1; i = e[i].l) if(e[i].t != p)
		for(IT var = up[e[i].t]->begin(); var != up[e[i].t]->end(); var++)
			(*up[s])[(var->first * mul[0] + e[i].v) % M] += var->second;
	for(i = ei[s]; i != -1; i = e[i].l) if(e[i].t != p)
		funcB(e[i].t, s, e[i].t, s, e[i].v, e[i].v % M, 0), delete up[e[i].t], up[e[i].t] = 0;
	ans += (*up[s])[0] - 1;
};
	scanf("%d%d", &n, &M);
	e = new Edge[2 * n];
	up = new unordered_map<int, int>*[n];
	memset(up, 0, n * sizeof(unordered_map<int, int>*));
	inv = new int[n]; mul = new int[n]{10 % M};
	ei = new int[n]; memset(ei, -1, n * sizeof(int));
	a = j = 0; b = i = 1; c = M; d = mul[0];
	while(true){
		k = c / d; l = c % d; if(!l) break;
		c = d; d = l; t = i; i = a; a = t - k * a; t = j; j = b; b = t - k * b;
	}
	inv[0] = b < 0 ? b + M : b;
	for(i = 1; i < n; i++){ mul[i] = (mul[i - 1] * mul[0]) % M; inv[i] = (inv[i - 1] * inv[0]) % M; }
	for(i = 0; i < n - 1; i++){
		scanf("%d%d%d", &a, &b, &c);
		e[2 * i].l = ei[a];	e[2 * i + 1].l = ei[b];
		e[2 * i].t = b;		e[2 * i + 1].t = a;
		e[2 * i].v = c;		e[2 * i + 1].v = c;
		ei[a] = 2 * i;		ei[b] = 2 * i + 1;
	}
	funcA(0, -1); delete up[0]; up[0] = 0;
	printf("%d", ans);
	return 0;
}


#include<bits/stdc++.h>
#include <unordered_map>
using std::unordered_map;
typedef long long ll;
int main(){
typedef void(*FuncA)(int, int);
typedef void(*FuncB)(int, int, int, int, int, ll, int);
typedef unordered_map<int, int>::iterator IT;
static ll ans = 0;
static int n, M, *ei;
static ll *mul, *inv;
static unordered_map<int, int> **up;
static int a, b, c, d, i, j, k, l, t;
static struct Edge{ int l, t, v; } *e;
static FuncB funcB = [](int s, int p, int r, int rp, int v, ll sum, int h){
	ll a = ((M - sum) * inv[h]) % M, b = ((a - (v % M) + M) * inv[0]) % M;
	IT t1 = up[rp]->find(a), t2 = up[r]->find(b);
	ans += (t1 != up[rp]->end() ? t1->second : 0)
		- (t2 != up[r]->end() ? t2->second : 0);
	int j;
	for(j = ei[s]; j != -1; j = e[j].l) if(e[j].t != p)
		funcB(e[j].t, s, r, rp, v, (sum * mul[0] + e[j].v) % M, h + 1);
};
static FuncA funcA = [](int s, int p){
	int i;
	for(i = ei[s]; i != -1; i = e[i].l)
		if(e[i].t != p) funcA(e[i].t, s);
	up[s] = new unordered_map<int, int>;
	for(i = ei[s], (*up[s])[0] = 1; i != -1; i = e[i].l) if(e[i].t != p)
		for(IT var = up[e[i].t]->begin(); var != up[e[i].t]->end(); var++)
			(*up[s])[(var->first * mul[0] + e[i].v) % M] += var->second;
	for(i = ei[s]; i != -1; i = e[i].l) if(e[i].t != p)
		funcB(e[i].t, s, e[i].t, s, e[i].v, e[i].v % M, 0), delete up[e[i].t], up[e[i].t] = 0;
	ans += (*up[s])[0] - 1;
};
	scanf("%d%d", &n, &M);
	e = new Edge[2 * n];
	up = new unordered_map<int, int>*[n];
	memset(up, 0, n * sizeof(unordered_map<int, int>*));
	inv = new int[n]; mul = new int[n]{10 % M};
	ei = new int[n]; memset(ei, -1, n * sizeof(int));
	a = j = 0; b = i = 1; c = M; d = mul[0];
	while(true){
		k = c / d; l = c % d; if(!l) break;
		c = d; d = l; t = i; i = a; a = t - k * a; t = j; j = b; b = t - k * b;
	}
	inv[0] = b < 0 ? b + M : b;
	for(i = 1; i < n; i++){ mul[i] = (mul[i - 1] * mul[0]) % M; inv[i] = (inv[i - 1] * inv[0]) % M; }
	for(i = 0; i < n - 1; i++){
		scanf("%d%d%d", &a, &b, &c);
		e[2 * i].l = ei[a];	e[2 * i + 1].l = ei[b];
		e[2 * i].t = b;		e[2 * i + 1].t = a;
		e[2 * i].v = c;		e[2 * i + 1].v = c;
		ei[a] = 2 * i;		ei[b] = 2 * i + 1;
	}
	funcA(0, -1); delete up[0]; up[0] = 0;
	printf("%d", ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 5000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
int U[SIZE],D[SIZE];
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w+Mod)%Mod;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    int xx=(d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+f+Mod)%Mod;
    int y=(d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    if(Son[x]) dfs2(Son[x],x,1);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    Additem(x);
    if(!opt){
        memset(U,0,sizeof(U));
        memset(D,0,sizeof(D));
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 2000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
int U[SIZE],D[SIZE];
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]%Mod+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w%Mod+Mod)%Mod;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    int xx=((d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+Mod)%Mod+f)%Mod;
    int y=((d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    if(Son[x]) dfs2(Son[x],x,1);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    Additem(x);
    if(!opt){
        memset(U,0,sizeof(U));
        memset(D,0,sizeof(D));
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    dfs1(1,0);
    dfs2(1,0,1);
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 2000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
map<int,int> U,D;
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]%Mod+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w)%Mod;
        // cout<<"down"<<y<<":"<<down[y]<<endl;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    // cout<<"sjdhfjksdhfjksdh fkjsdhkfjsdhfkjsdhjkfhsdkjfhsdkjfhsdjkfh"<<x<<" "<<LCA<<endl;
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    // cout<<"a:"<<a<<" "<<"b:"<<b<<" "<<"c:"<<c<<" d:"<<d<<" e:"<<e<<" f:"<<f<<endl;
    int xx=((d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+Mod)%Mod+f)%Mod;
    int y=((d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    // cout<<"xx:"<<xx<<" "<<"y:"<<y<<endl;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    // cout<<"x:"<<x<<endl;
    if(Son[x]){
        // cout<<"Son:"<<Son[x]<<endl;
        dfs2(Son[x],x,1);
    }
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    // cout<<"x:"<<x<<endl;
    Additem(x);
    if(!opt){
        U.clear();D.clear();
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    // cout<<1<<endl;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    // cout<<2<<endl;
    dfs1(1,0);
    // for(int i=1;i<=10;i++) cout<<down[i]<<" ";
    // cout<<3<<endl;
    dfs2(1,0,1);
    // cout<<4<<endl;
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 1000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
int U[SIZE],D[SIZE];
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w+Mod)%Mod;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    int xx=(d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+f+Mod)%Mod;
    int y=(d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    if(Son[x]) dfs2(Son[x],x,1);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    Additem(x);
    if(!opt){
        memset(U,0,sizeof(U));
        memset(D,0,sizeof(D));
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 2000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
int U[SIZE],D[SIZE];
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w+Mod)%Mod;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    int xx=(d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+f+Mod)%Mod;
    int y=(d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    if(Son[x]) dfs2(Son[x],x,1);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    Additem(x);
    if(!opt){
        memset(U,0,sizeof(U));
        memset(D,0,sizeof(D));
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 4000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
int U[SIZE],D[SIZE];
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w+Mod)%Mod;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    int xx=(d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+f+Mod)%Mod;
    int y=(d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    if(Son[x]) dfs2(Son[x],x,1);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    Additem(x);
    if(!opt){
        memset(U,0,sizeof(U));
        memset(D,0,sizeof(D));
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define SIZE 2000010
#define int long long
int Head[SIZE],Ver[SIZE],Next[SIZE],Edge[SIZE];
int tot=0;
int tenm[SIZE];
int ans=0;
int fa[SIZE],dep[SIZE],siz[SIZE],Son[SIZE];
int up[SIZE],down[SIZE];
int U[SIZE],D[SIZE];
void Add(int x,int y,int z){
    Ver[++tot]=y;
    Next[tot]=Head[x];
    Head[x]=tot;
    Edge[tot]=z;
}
int n,Mod;
void dfs1(int x,int Fa){
    siz[x]=1;
    int Mx=-1;
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i],w=Edge[i];
        if(y==Fa) continue;
        up[y]=(up[x]%Mod+w*tenm[dep[x]]%Mod+Mod)%Mod;
        down[y]=(10*down[x]%Mod+w%Mod+Mod)%Mod;
        dep[y]=dep[x]+1;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>Mx) Mx=siz[y],Son[x]=y;
    }
}
void Exgcd(int a,int b,int &x,int &y){
    if(!b) x=1,y=0;
    else{
        Exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int Inv(int a){
    int x,y;
    Exgcd(a,Mod,x,y);
    x=(x%Mod+Mod)%Mod;
    return x;
}
void Additem(int x){
    U[up[x]]++;
    D[down[x]*Inv(tenm[dep[x]])%Mod]++;
}
void Calc(int x,int LCA){
    int a=up[x],b=tenm[dep[LCA]],c=tenm[dep[x]];
    int d=down[LCA],e=down[x],f=up[LCA];
    int xx=((d*b%Mod-e*b%Mod*b%Mod*Inv(c)%Mod+Mod)%Mod+f)%Mod;
    int y=((d*Inv(b)%Mod+(f-a)*Inv(b)%Mod*Inv(b)%Mod)%Mod+Mod)%Mod;
    xx=(xx+Mod)%Mod;y=(y+Mod)%Mod;
    ans+=U[xx];
    ans+=D[y];
}
void update(int x,int Fa,int LCA,int opt){
    if(opt) Calc(x,LCA);
    else Additem(x);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa) continue;
        update(y,x,LCA,opt);
    }
}
void dfs2(int x,int Fa,int opt){
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        dfs2(y,x,0);
    }
    if(Son[x]) dfs2(Son[x],x,1);
    for(int i=Head[x];i;i=Next[i]){
        int y=Ver[i];
        if(y==Fa||y==Son[x]) continue;
        update(y,x,x,1);
        update(y,x,x,0);
    }
    Calc(x,x);
    Additem(x);
    if(!opt){
        memset(U,0,sizeof(U));
        memset(D,0,sizeof(D));
    }
}
signed main(){
    scanf("%lld%lld",&n,&Mod);
    tenm[0]=1;
    for(int i=1;i<=n+4;i++) tenm[i]=tenm[i-1]*10%Mod;
    for(int i=1;i<=n-1;i++){
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        Add(x+1,y+1,z);Add(y+1,x+1,z);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    printf("%lld\n",ans);
    return 0;
}


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;

typedef long long ll;

const int MAX_N=1e5+10;
const int INF=1e9+10;

int N,MOD;
bool centroid[MAX_N];
int subtree_size[MAX_N];
vector <pair<int,int> > g[MAX_N];

int compute_subtree_size(int v,int p){
	int c=1;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		c+=compute_subtree_size(g[v][i].fst,v);
	}
	subtree_size[v]=c;
	return c;
}

pair<int,int> search_centroid(int v,int p,int t){
	pair<int,int> res=make_pair(INF,-1);
	int s=1,m=0;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		res=min(res,search_centroid(w,v,t));
		m=max(m,subtree_size[w]);
		s+=subtree_size[w];
	}
	m=max(m,t-s);
	res=min(res,make_pair(m,v));
	return res;
}

vector <pair<int,int> > v,tot;

void compute_subtree_value(int x,int fa,int value,int lenth){
//	cout<<x<<" "<<fa<<" "<<value<<" "<<lenth<<endl;
	v.pb(mp(value,lenth));
	if(centroid[x]) return;
	for(int i=0;i<g[x].size();i++){
		int to=g[x][i].fst;
		if(to==fa) continue;
		ll now=1ll*value*10ll%MOD+g[x][i].snd; now%=MOD;
		if(centroid[to]) continue;
		compute_subtree_value(to,x,now,lenth+1);
	}
}

map <int,int> Map,nMap;
ll ans=0;
ll p10[MAX_N];

void solve(){
	nMap.clear();
	for(int i=0;i<v.size();i++) nMap[v[i].fst]++;
//	for(int i=0;i<v.size();i++) cout<<v[i].fst<<","<<v[i].snd<<" "; cout<<endl;
	for(int i=0;i<v.size();i++){
		ll now=1ll*v[i].fst*p10[v[i].snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans-=nMap[now];
	//	cout<<v[i].fst<<","<<v[i].snd<<","<<now<<","<<nMap[now]<<" ";
	}
	for(int i=0;i<v.size();i++) Map[v[i].fst]++;
	for(int i=0;i<v.size();i++) tot.pb(v[i]);
}

void solve_subproblem(int x){
	compute_subtree_size(x,-1);
	int s=search_centroid(x,-1,subtree_size[x]).snd;
	centroid[s]=true;
//	cout<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	for(int i=0;i<g[s].size();i++){
		if(centroid[g[s][i].fst]) continue;
		solve_subproblem(g[s][i].fst);
	}
//	cout<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	Map.clear(); tot.clear();
	for(int i=0;i<g[s].size();i++){
		int to=g[s][i].fst;
		v.clear();
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" "; cout<<endl;
		compute_subtree_value(to,s,g[s][i].snd%MOD,1);
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" ";
	//	cout<<endl;
		solve();
	}
//	cout<<"s="<<s<<endl;
//	for(int i=0;i<tot.size();i++) cout<<tot[i].fst<<","<<tot[i].snd<<" "; cout<<endl;
//	for(map <int,int>::iterator it=Map.begin();it!=Map.end();it++)
//		cout<<it->fst<<","<<it->snd<<" ";
//	cout<<endl;
	for(int i=0;i<tot.size();i++){
		ll now=1ll*tot[i].fst*p10[tot[i].snd]; now%=MOD;
		now=MOD-now; now%=MOD;
//		cout<<tot[i].fst<<","<<tot[i].snd<<","<<now<<","<<Map[now]<<" ";
		ans+=Map[now];
	}
//	cout<<endl;
}

ll extgcd(ll a,ll b,ll &x, ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return d;
}

ll mod_inverse(ll a,ll mod){
	ll x,y;
	extgcd(a,mod,x,y);
	return (mod+x%mod)%mod;
}

int main(){
	scanf("%d%d",&N,&MOD);
	p10[1]=mod_inverse(10,MOD);
	for(int i=2;i<MAX_N;i++) p10[i]=1ll*p10[i-1]*p10[1]%MOD;
//	for(int i=1;i<5;i++) cout<<p10[i]<<" "; cout<<endl;
	for(int i=0;i<N-1;i++){
		int u,v,cost;
		scanf("%d%d%d",&u,&v,&cost);
		g[u].pb(mp(v,cost));
		g[v].pb(mp(u,cost));
		if(cost%MOD==0) ans+=2;
	}
	solve_subproblem(0);
	printf("%lld\n",ans);
	return 0;
}

/*
6 7
0 1 2
4 2 4
2 0 1
3 0 9
2 5 7
*/


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;

typedef long long ll;

const int MAX_N=1e5+10;
const int INF=1e9+10;

int N;
ll MOD;
bool centroid[MAX_N];
int subtree_size[MAX_N];
vector <pair<int,int> > g[MAX_N];

int compute_subtree_size(int v,int p){
	int c=1;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		c+=compute_subtree_size(g[v][i].fst,v);
	}
	subtree_size[v]=c;
	return c;
}

pair<int,int> search_centroid(int v,int p,int t){
	pair<int,int> res=make_pair(INF,-1);
	int s=1,m=0;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		res=min(res,search_centroid(w,v,t));
		m=max(m,subtree_size[w]);
		s+=subtree_size[w];
	}
	m=max(m,t-s);
	res=min(res,make_pair(m,v));
	return res;
}

vector <pair<int,pair<int,int> > > v,tot;

void compute_subtree_value(int x,int fa,int value1,int value2,int lenth,int p){
//	cout<<x<<" "<<fa<<" "<<value<<" "<<lenth<<endl;
	v.pb(mp(value1,mp(value2,lenth)));
	if(centroid[x]) return;
	for(int i=0;i<g[x].size();i++){
		int to=g[x][i].fst;
		if(to==fa||centroid[to]) continue;
		ll now2=1ll*value2*10ll%MOD+g[x][i].snd; now2%=MOD;
		ll now1=g[x][i].snd*p%MOD; now1+=value1; now1%=MOD;
		compute_subtree_value(to,x,now1,now2,lenth+1,1ll*p*10ll%MOD);
	}
}

map <int,int> Map,nMap;
ll ans=0;
ll p10[MAX_N];

void solve(){
	nMap.clear();
	for(int i=0;i<v.size();i++) nMap[v[i].fst]++;
//	for(int i=0;i<v.size();i++) cout<<v[i].fst<<","<<v[i].snd<<" "; cout<<endl;
	for(int i=0;i<v.size();i++){
		ll now=1ll*v[i].snd.fst*p10[v[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans-=nMap[now];
	//	cout<<"-"<<v[i].fst<<","<<v[i].snd<<","<<now<<","<<nMap[now]<<" ";
	}
//	cout<<endl;
	for(int i=0;i<v.size();i++) Map[v[i].fst]++;
	for(int i=0;i<v.size();i++) tot.pb(v[i]);
}

void solve_subproblem(int x){
	compute_subtree_size(x,-1);
	int s=search_centroid(x,-1,subtree_size[x]).snd;
	centroid[s]=true;
//	cout<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	for(int i=0;i<g[s].size();i++){
		if(centroid[g[s][i].fst]) continue;
		solve_subproblem(g[s][i].fst);
	}
//	cout<<"s="<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	Map.clear(); tot.clear(); tot.pb(mp(0,mp(0,0))); Map[0]++;
	for(int i=0;i<g[s].size();i++){
		int to=g[s][i].fst;
	//	cout<<to<<","<<centroid[to]<<" ";
		if(centroid[to]) continue;
		v.clear();
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" "; cout<<endl;
		compute_subtree_value(to,s,g[s][i].snd%MOD,g[s][i].snd%MOD,1,10);
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" ";
	//	cout<<endl;
		solve();
	}
//	cout<<endl;
//	cout<<"s="<<s<<endl;
//	for(int i=0;i<tot.size();i++) cout<<tot[i].fst<<","<<tot[i].snd<<" "; cout<<endl;
//	for(map <int,int>::iterator it=Map.begin();it!=Map.end();it++)
//		cout<<it->fst<<","<<it->snd<<" ";
//	cout<<endl;
	for(int i=0;i<tot.size();i++){
		ll now=1ll*tot[i].snd.fst*p10[tot[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
	//	cout<<tot[i].fst<<","<<tot[i].snd<<","<<now<<","<<Map[now]<<" ";
		ans+=Map[now];
	}
//	cout<<endl;
	centroid[s]=false;
}

ll extgcd(ll a,ll b,ll &x, ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return d;
}

ll mod_inverse(ll a,ll mod){
	ll x,y;
	extgcd(a,mod,x,y);
	return (mod+x%mod)%mod;
}

int main(){
	scanf("%d%d",&N,&MOD);
	p10[0]=1;
	p10[1]=mod_inverse(10,MOD);
	for(int i=2;i<MAX_N;i++) p10[i]=1ll*p10[i-1]*p10[1]%MOD;
//	for(int i=1;i<5;i++) cout<<p10[i]<<" "; cout<<endl;
	for(int i=0;i<N-1;i++){
		int u,v,cost;
		scanf("%d%d%d",&u,&v,&cost);
		g[u].pb(mp(v,cost));
		g[v].pb(mp(u,cost));
	}
	solve_subproblem(0);
	ans-=N;
	printf("%lld\n",ans);
	return 0;
}

/*
6 7
0 1 2
4 2 4
2 0 1
3 0 9
2 5 7
*/


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;

typedef long long ll;

const int MAX_N=1e5+10;
const int INF=1e9+10;

int N,MOD;
bool centroid[MAX_N];
int subtree_size[MAX_N];
vector <pair<int,int> > g[MAX_N];

int compute_subtree_size(int v,int p){
	int c=1;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		c+=compute_subtree_size(g[v][i].fst,v);
	}
	subtree_size[v]=c;
	return c;
}

pair<int,int> search_centroid(int v,int p,int t){
	pair<int,int> res=make_pair(INF,-1);
	int s=1,m=0;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		res=min(res,search_centroid(w,v,t));
		m=max(m,subtree_size[w]);
		s+=subtree_size[w];
	}
	m=max(m,t-s);
	res=min(res,make_pair(m,v));
	return res;
}

vector <pair<int,int> > v,tot;

void compute_subtree_value(int x,int fa,int value,int lenth){
//	cout<<x<<" "<<fa<<" "<<value<<" "<<lenth<<endl;
	v.pb(mp(value,lenth));
	if(centroid[x]) return;
	for(int i=0;i<g[x].size();i++){
		int to=g[x][i].fst;
		if(to==fa) continue;
		ll now=1ll*value*10ll%MOD+g[x][i].snd; now%=MOD;
		if(centroid[to]) continue;
		compute_subtree_value(to,x,now,lenth+1);
	}
}

map <int,int> Map,nMap;
ll ans=0;
ll p10[MAX_N];

void solve(){
	nMap.clear();
	for(int i=0;i<v.size();i++) nMap[v[i].fst]++;
//	for(int i=0;i<v.size();i++) cout<<v[i].fst<<","<<v[i].snd<<" "; cout<<endl;
	for(int i=0;i<v.size();i++){
		ll now=1ll*v[i].fst*p10[v[i].snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans-=nMap[now];
	//	cout<<v[i].fst<<","<<v[i].snd<<","<<now<<","<<nMap[now]<<" ";
	}
	for(int i=0;i<v.size();i++) Map[v[i].fst]++;
	for(int i=0;i<v.size();i++) tot.pb(v[i]);
}

void solve_subproblem(int x){
	compute_subtree_size(x,-1);
	int s=search_centroid(x,-1,subtree_size[x]).snd;
	centroid[s]=true;
//	cout<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	for(int i=0;i<g[s].size();i++){
		if(centroid[g[s][i].fst]) continue;
		solve_subproblem(g[s][i].fst);
	}
//	cout<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	Map.clear(); tot.clear();
	for(int i=0;i<g[s].size();i++){
		int to=g[s][i].fst;
		v.clear();
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" "; cout<<endl;
		compute_subtree_value(to,s,g[s][i].snd%MOD,1);
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" ";
	//	cout<<endl;
		solve();
	}
//	cout<<"s="<<s<<endl;
//	for(int i=0;i<tot.size();i++) cout<<tot[i].fst<<","<<tot[i].snd<<" "; cout<<endl;
//	for(map <int,int>::iterator it=Map.begin();it!=Map.end();it++)
//		cout<<it->fst<<","<<it->snd<<" ";
//	cout<<endl;
	for(int i=0;i<tot.size();i++){
		ll now=1ll*tot[i].fst*p10[tot[i].snd]; now%=MOD;
		now=MOD-now; now%=MOD;
//		cout<<tot[i].fst<<","<<tot[i].snd<<","<<now<<","<<Map[now]<<" ";
		ans+=Map[now];
	}
//	cout<<endl;
	centroid[s]=false;
}

ll extgcd(ll a,ll b,ll &x, ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return d;
}

ll mod_inverse(ll a,ll mod){
	ll x,y;
	extgcd(a,mod,x,y);
	return (mod+x%mod)%mod;
}

int main(){
	scanf("%d%d",&N,&MOD);
	p10[1]=mod_inverse(10,MOD);
	for(int i=2;i<MAX_N;i++) p10[i]=1ll*p10[i-1]*p10[1]%MOD;
//	for(int i=1;i<5;i++) cout<<p10[i]<<" "; cout<<endl;
	for(int i=0;i<N-1;i++){
		int u,v,cost;
		scanf("%d%d%d",&u,&v,&cost);
		g[u].pb(mp(v,cost));
		g[v].pb(mp(u,cost));
		if(cost%MOD==0) ans+=2;
	}
	solve_subproblem(0);
	printf("%lld\n",ans);
	return 0;
}

/*
6 7
0 1 2
4 2 4
2 0 1
3 0 9
2 5 7
*/


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;

typedef long long ll;

const int MAX_N=1e5+10;
const int INF=1e9+10;

int N;
ll MOD;
bool centroid[MAX_N];
int subtree_size[MAX_N];
vector <pair<int,int> > g[MAX_N];

int compute_subtree_size(int v,int p){
	int c=1;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		c+=compute_subtree_size(g[v][i].fst,v);
	}
	subtree_size[v]=c;
	return c;
}

pair<int,int> search_centroid(int v,int p,int t){
	pair<int,int> res=make_pair(INF,-1);
	int s=1,m=0;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		res=min(res,search_centroid(w,v,t));
		m=max(m,subtree_size[w]);
		s+=subtree_size[w];
	}
	m=max(m,t-s);
	res=min(res,make_pair(m,v));
	return res;
}

vector <pair<int,pair<int,int> > > v,tot;

void compute_subtree_value(int x,int fa,int value1,int value2,int lenth,int p){
	v.pb(mp(value1,mp(value2,lenth)));
	if(centroid[x]) return;
	for(int i=0;i<g[x].size();i++){
		int to=g[x][i].fst;
		if(to==fa||centroid[to]) continue;
		ll now2=1ll*value2*10ll%MOD+g[x][i].snd; now2%=MOD;
		ll now1=1ll*g[x][i].snd*p%MOD; now1+=value1; now1%=MOD;
		compute_subtree_value(to,x,now1,now2,lenth+1,1ll*p*10ll%MOD);
	}
}

map <int,int> Map,nMap;
ll ans=0;
ll p10[MAX_N];

void solve(){
	nMap.clear();
	for(int i=0;i<v.size();i++) nMap[v[i].fst]++;
	for(int i=0;i<v.size();i++){
		ll now=1ll*v[i].snd.fst*p10[v[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans-=nMap[now];
	}
	for(int i=0;i<v.size();i++) Map[v[i].fst]++;
	for(int i=0;i<v.size();i++) tot.pb(v[i]);
}

void solve_subproblem(int x){
	compute_subtree_size(x,-1);
	int s=search_centroid(x,-1,subtree_size[x]).snd;
	centroid[s]=true;
	for(int i=0;i<g[s].size();i++){
		if(centroid[g[s][i].fst]) continue;
		solve_subproblem(g[s][i].fst);
	}
	Map.clear(); tot.clear();
	tot.pb(mp(0,mp(0,0))); Map[0]++;
	for(int i=0;i<g[s].size();i++){
		int to=g[s][i].fst;
		if(centroid[to]) continue;
		v.clear();
		compute_subtree_value(to,s,g[s][i].snd%MOD,g[s][i].snd%MOD,1,10%MOD);
		solve();
	}
	for(int i=0;i<tot.size();i++){
		ll now=1ll*tot[i].snd.fst*p10[tot[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans+=Map[now];
	}
	centroid[s]=false;
}

ll extgcd(ll a,ll b,ll &x, ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return d;
}

ll mod_inverse(ll a,ll mod){
	ll x,y;
	extgcd(a,mod,x,y);
	return (mod+x%mod)%mod;
}

int main(){
	scanf("%d%lld",&N,&MOD);
	p10[0]=1;
	p10[1]=mod_inverse(10,MOD)%MOD;
	for(int i=2;i<MAX_N;i++) p10[i]=1ll*p10[i-1]*p10[1]%MOD;
	for(int i=0;i<N-1;i++){
		int u,v,cost;
		scanf("%d%d%d",&u,&v,&cost);
		g[u].pb(mp(v,cost));
		g[v].pb(mp(u,cost));
	}
	solve_subproblem(0);
	ans-=N;
	printf("%lld\n",ans);
	return 0;
}

/*
6 7
0 1 2
4 2 4
2 0 1
3 0 9
2 5 7
*/


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;

typedef long long ll;

const int MAX_N=1e5+10;
const int INF=1e9+10;

int N;
ll MOD;
bool centroid[MAX_N];
int subtree_size[MAX_N];
vector <pair<int,int> > g[MAX_N];

int compute_subtree_size(int v,int p){
	int c=1;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		c+=compute_subtree_size(g[v][i].fst,v);
	}
	subtree_size[v]=c;
	return c;
}

pair<int,int> search_centroid(int v,int p,int t){
	pair<int,int> res=make_pair(INF,-1);
	int s=1,m=0;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		res=min(res,search_centroid(w,v,t));
		m=max(m,subtree_size[w]);
		s+=subtree_size[w];
	}
	m=max(m,t-s);
	res=min(res,make_pair(m,v));
	return res;
}

vector <pair<int,pair<int,int> > > v,tot;

void compute_subtree_value(int x,int fa,int value1,int value2,int lenth,int p){
	v.pb(mp(value1,mp(value2,lenth)));
	if(centroid[x]) return;
	for(int i=0;i<g[x].size();i++){
		int to=g[x][i].fst;
		if(to==fa||centroid[to]) continue;
		ll now2=1ll*value2*10ll%MOD+g[x][i].snd; now2%=MOD;
		ll now1=g[x][i].snd*p%MOD; now1+=value1; now1%=MOD;
		compute_subtree_value(to,x,now1,now2,lenth+1,1ll*p*10ll%MOD);
	}
}

map <int,int> Map,nMap;
ll ans=0;
ll p10[MAX_N];

void solve(){
	nMap.clear();
	for(int i=0;i<v.size();i++) nMap[v[i].fst]++;
	for(int i=0;i<v.size();i++){
		ll now=1ll*v[i].snd.fst*p10[v[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans-=nMap[now];
	}
	for(int i=0;i<v.size();i++) Map[v[i].fst]++;
	for(int i=0;i<v.size();i++) tot.pb(v[i]);
}

void solve_subproblem(int x){
	compute_subtree_size(x,-1);
	int s=search_centroid(x,-1,subtree_size[x]).snd;
	centroid[s]=true;
	for(int i=0;i<g[s].size();i++){
		if(centroid[g[s][i].fst]) continue;
		solve_subproblem(g[s][i].fst);
	}
	Map.clear(); tot.clear(); tot.pb(mp(0,mp(0,0))); Map[0]++;
	for(int i=0;i<g[s].size();i++){
		int to=g[s][i].fst;
		if(centroid[to]) continue;
		v.clear();
		compute_subtree_value(to,s,g[s][i].snd%MOD,g[s][i].snd%MOD,1,10%MOD);
		solve();
	}
	for(int i=0;i<tot.size();i++){
		ll now=1ll*tot[i].snd.fst*p10[tot[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans+=Map[now];
	}
	centroid[s]=false;
}

ll extgcd(ll a,ll b,ll &x, ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return d;
}

ll mod_inverse(ll a,ll mod){
	ll x,y;
	extgcd(a,mod,x,y);
	return (mod+x%mod)%mod;
}

int main(){
	scanf("%d%lld",&N,&MOD);
	p10[0]=1;
	p10[1]=mod_inverse(10,MOD);
	for(int i=2;i<MAX_N;i++) p10[i]=1ll*p10[i-1]*p10[1]%MOD;
	for(int i=0;i<N-1;i++){
		int u,v,cost;
		scanf("%d%d%d",&u,&v,&cost);
		g[u].pb(mp(v,cost));
		g[v].pb(mp(u,cost));
	}
	solve_subproblem(0);
	ans-=N;
	printf("%lld\n",ans);
	return 0;
}

/*
6 7
0 1 2
4 2 4
2 0 1
3 0 9
2 5 7
*/


#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
using namespace std;

typedef long long ll;

const int MAX_N=1e5+10;
const int INF=1e9+10;

int N,MOD;
bool centroid[MAX_N];
int subtree_size[MAX_N];
vector <pair<int,int> > g[MAX_N];

int compute_subtree_size(int v,int p){
	int c=1;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		c+=compute_subtree_size(g[v][i].fst,v);
	}
	subtree_size[v]=c;
	return c;
}

pair<int,int> search_centroid(int v,int p,int t){
	pair<int,int> res=make_pair(INF,-1);
	int s=1,m=0;
	for(int i=0;i<g[v].size();i++){
		int w=g[v][i].fst;
		if(w==p||centroid[w]) continue;
		res=min(res,search_centroid(w,v,t));
		m=max(m,subtree_size[w]);
		s+=subtree_size[w];
	}
	m=max(m,t-s);
	res=min(res,make_pair(m,v));
	return res;
}

vector <pair<int,pair<int,int> > > v,tot;

void compute_subtree_value(int x,int fa,int value1,int value2,int lenth,int p){
//	cout<<x<<" "<<fa<<" "<<value<<" "<<lenth<<endl;
	v.pb(mp(value1,mp(value2,lenth)));
	if(centroid[x]) return;
	for(int i=0;i<g[x].size();i++){
		int to=g[x][i].fst;
		if(to==fa||centroid[to]) continue;
		ll now2=1ll*value2*10ll%MOD+g[x][i].snd; now2%=MOD;
		ll now1=g[x][i].snd*p%MOD; now1+=value1; now1%=MOD;
		compute_subtree_value(to,x,now1,now2,lenth+1,p*10%MOD);
	}
}

map <int,int> Map,nMap;
ll ans=0;
ll p10[MAX_N];

void solve(){
	nMap.clear();
	for(int i=0;i<v.size();i++) nMap[v[i].fst]++;
//	for(int i=0;i<v.size();i++) cout<<v[i].fst<<","<<v[i].snd<<" "; cout<<endl;
	for(int i=0;i<v.size();i++){
		ll now=1ll*v[i].snd.fst*p10[v[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
		ans-=nMap[now];
	//	cout<<"-"<<v[i].fst<<","<<v[i].snd<<","<<now<<","<<nMap[now]<<" ";
	}
//	cout<<endl;
	for(int i=0;i<v.size();i++) Map[v[i].fst]++;
	for(int i=0;i<v.size();i++) tot.pb(v[i]);
}

void solve_subproblem(int x){
	compute_subtree_size(x,-1);
	int s=search_centroid(x,-1,subtree_size[x]).snd;
	centroid[s]=true;
//	cout<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	for(int i=0;i<g[s].size();i++){
		if(centroid[g[s][i].fst]) continue;
		solve_subproblem(g[s][i].fst);
	}
//	cout<<"s="<<s<<endl;
//	for(int i=0;i<N;i++) cout<<centroid[i]<<" "; cout<<endl;
	Map.clear(); tot.clear(); tot.pb(mp(0,mp(0,0))); Map[0]++;
	for(int i=0;i<g[s].size();i++){
		int to=g[s][i].fst;
	//	cout<<to<<","<<centroid[to]<<" ";
		if(centroid[to]) continue;
		v.clear();
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" "; cout<<endl;
		compute_subtree_value(to,s,g[s][i].snd%MOD,g[s][i].snd%MOD,1,10);
	//	for(int j=0;j<v.size();j++) cout<<v[j].fst<<","<<v[j].snd<<" ";
	//	cout<<endl;
		solve();
	}
//	cout<<endl;
//	cout<<"s="<<s<<endl;
//	for(int i=0;i<tot.size();i++) cout<<tot[i].fst<<","<<tot[i].snd<<" "; cout<<endl;
//	for(map <int,int>::iterator it=Map.begin();it!=Map.end();it++)
//		cout<<it->fst<<","<<it->snd<<" ";
//	cout<<endl;
	for(int i=0;i<tot.size();i++){
		ll now=1ll*tot[i].snd.fst*p10[tot[i].snd.snd]; now%=MOD;
		now=MOD-now; now%=MOD;
	//	cout<<tot[i].fst<<","<<tot[i].snd<<","<<now<<","<<Map[now]<<" ";
		ans+=Map[now];
	}
//	cout<<endl;
	centroid[s]=false;
}

ll extgcd(ll a,ll b,ll &x, ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return d;
}

ll mod_inverse(ll a,ll mod){
	ll x,y;
	extgcd(a,mod,x,y);
	return (mod+x%mod)%mod;
}

int main(){
	scanf("%d%d",&N,&MOD);
	p10[0]=1;
	p10[1]=mod_inverse(10,MOD);
	for(int i=2;i<MAX_N;i++) p10[i]=1ll*p10[i-1]*p10[1]%MOD;
//	for(int i=1;i<5;i++) cout<<p10[i]<<" "; cout<<endl;
	for(int i=0;i<N-1;i++){
		int u,v,cost;
		scanf("%d%d%d",&u,&v,&cost);
		g[u].pb(mp(v,cost));
		g[v].pb(mp(u,cost));
	}
	solve_subproblem(0);
	ans-=N;
	printf("%lld\n",ans);
	return 0;
}

/*
6 7
0 1 2
4 2 4
2 0 1
3 0 9
2 5 7
*/


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<ll,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

void init(){
    int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;p[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
    }
}

/*void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}*/

void down(int u,int f,int w,int d) {
	if (w==0) ++res;
	ans+=hs[(m-w)*inv[d]%m];
	for (auto p:G[u]) {
		int v=p.fi;
		if (v==f||del[v]) continue;
		down(v,u,(10ll*w+p.se)%m,d+1);
	}
}

void up(int u,int f,int w,int d) {
	if (w==0) ++res;
	hs[w]++;
	for (auto t:G[u]) {
		int v=t.fi;
		if (v==f||del[v]) continue;
		up(v,u,(w+t.se*p[d])%m,d+1);
	}
}

void work(int u){
    root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);del[root]=true;
    //
    hs.clear();
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[root]));
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    int rt=root;
    for(int i=0;i<G[rt].size();i++){
        int v=G[rt][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<ll,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

void init(){
    int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;p[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
        del[i]=false;
    }
}

void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}

void work(int u){
    root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);del[root]=true;
    //
    hs.clear();
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[root]));
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    int rt=root;
    for(int i=0;i<G[rt].size();i++){
        int v=G[rt][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<ll,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

ll INV(ll q,ll m) {
	q%=m;if (q<0) q+=m;
	if (q==0) return 0;
	ll a1=m,b1=0,a2=q,b2=1,a3=0,b3=0,t=0;
	while (a2!=1) {	t=a1/a2,a3=a1-t*a2,b3=b1-t*b2%m,
		a1=a2,a2=a3,b1=b2,b2=b3;if (b2<0) b2+=m;}
	return b2;
}

void init(){
    /*int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;*/
    p[0]=inv[0]=1;ll x=INV(10,m);
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
        del[i]=false;
    }
}

void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}

void work(int u){
    root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);del[root]=true;
    //
    hs.clear();
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[root]));
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    int rt=root;
    for(int i=0;i<G[rt].size();i++){
        int v=G[rt][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<ll,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

void init(){
    int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;p[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
    }
}

void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}

void work(int u){
    root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);u=root;
    //
    hs.clear();
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[u]));
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    del[u]=true;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<ll,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

void init(){
    int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;p[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
    }
}

void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}

int q[MAXN],ms[MAXN],f[MAXN];

int find(int u) {
	int t=1;q[0]=u;f[u]=-1;
	rep(i,0,t) {
		u=q[i];
		rep(j,0,G[u].size()) {
			int v=G[u][j].fi;
			if (!del[v]&&v!=f[u]) f[q[t++]=v]=u;
		}
		ms[q[i]]=0;
		sz[q[i]]=1;
	}
	for (int i=t-1;i>=0;i--) {
		ms[q[i]]=max(ms[q[i]],t-sz[q[i]]);
		if (ms[q[i]]*2<=t) return q[i];
		sz[f[q[i]]]+=sz[q[i]];
		ms[f[q[i]]]=max(ms[f[q[i]]],sz[q[i]]);
	}
	return 0;
}

void work(int u){
    //root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);del[root]=true;
    root=find(u);del[root]=true;
    //
    hs.clear();
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[root]));
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    int rt=root;
    for(int i=0;i<G[rt].size();i++){
        int v=G[rt][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<ll,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

void init(){
    int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;p[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
    }
}

void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}

void work(int u){
    root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);
    //
    hs.clear();
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[root]));
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    del[root]=true;int rt=root;
    for(int i=0;i<G[rt].size();i++){
        int v=G[rt][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
#define sf scanf
#define pf printf
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
typedef long long ll;
typedef long double ld;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
const double PI=acos(-1.0);
const int MAXN=1e5+5;
const int MOD=1e9+7;
int sgn(double x){if(fabs(x)<eps)return 0;if(x<0)return -1;else return 1;}
ll pw(ll a,ll n,ll mod){ll ret=1;while(n){if(n&1)ret=ret*a%mod;a=a*a%mod;n>>=1;}return ret;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
//head

int n,m;
vector<pii>G[MAXN];
ll ans,res;
int root,sz[MAXN],mx[MAXN];
bool del[MAXN];

void dfs1(int u,int fa){
    sz[u]=1;mx[u]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs1(v,u);
            sz[u]+=sz[v];
            mx[u]=max(mx[u],sz[v]);
        }
    }
}

void dfs2(int u,int fa,int sum){
    mx[u]=max(mx[u],sum-sz[u]);
    if(mx[root]>mx[u])root=u;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi;
        if(v!=fa&&!del[v]){
            dfs2(v,u,sum);
        }
    }
}

ll inv[MAXN],p[MAXN];
map<int,int>hs;

void ex_gcd(int a,int b,int &x,int &y,int &d){
    if(b==0){d=a;x=1;y=0;}
    else{
        ex_gcd(b,a%b,y,x,d);
        y=y-x*(a/b);
    }
}

void init(){
    int x,y,d;ex_gcd(10,m,x,y,d);
    x=(x%m+m)%m;p[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        p[i]=p[i-1]*10%m;
        inv[i]=inv[i-1]*x%m;
        del[i]=false;
    }
}

void down(int u,int fa,int s,int dep){
    if(s==0)res++;
    ans+=hs[(ll)(m-s)*inv[dep]%m];
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            down(v,u,(10ll*s+w)%m,dep+1);
        }
    }
}

void up(int u,int fa,ll s,int dep){
    if(s==0)res++;
    hs[s]++;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v!=fa&&!del[v]){
            up(v,u,(s+(ll)w*p[dep])%m,dep+1);
        }
    }
}

void work(int u){
    root=u;dfs1(u,-1);dfs2(u,-1,sz[u]);del[root]=true;
    //
    hs.clear();
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    hs.clear();
    reverse(all(G[root]));
    for(int i=0;i<G[root].size();i++){
        int v=G[root][i].fi,w=G[root][i].se;
        if(!del[v]){
            down(v,u,w,1);
            up(v,u,w,1);
        }
    }
    //
    int rt=root;
    for(int i=0;i<G[rt].size();i++){
        int v=G[rt][i].fi;
        if(!del[v])work(v);
    }
}

int main(){
    sf("%d%d",&n,&m);
    init();int u,v,w;
    for(int i=1;i<n;i++){
        sf("%d%d%d",&u,&v,&w);w%=m;
        G[u].pb(mp(v,w));
        G[v].pb(mp(u,w));
    }
    ans=res=0;work(0);//de(res);
    pf("%I64d\n",ans+res/2);
}


#include <bits/stdc++.h>

#define ll long long
#define Max 100005

using namespace std;

inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline ll read(){
    ll x=0;char ch=gc();bool positive=1;
    for(;!isdigit(ch);ch=gc())if(ch=='-')positive=0;
    for(;isdigit(ch);ch=gc())x=x*10+ch-'0';
    return positive?x:-x;
}

inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}

inline void writeln(ll x){
    write(x);puts("");
}

struct Edge{
    ll v,to,w;
}e[Max*2];

struct Node{
    ll sum1,sum2,dep;
}stk[Max];

ll n,k,l,r,w,sum,ans,top,root,size,son[Max],tot[Max],head[Max];
bool vis[Max];
map<int,int>dis;

inline void add(ll u,ll v,ll w){
    e[++size].v=v;e[size].to=head[u];e[size].w=w;head[u]=size;
}

inline void getrt(ll u,ll fa){
    son[u]=1;
    tot[u]=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getrt(v,u);
        son[u]+=son[v];
        tot[u]=max(tot[u],son[v]);
    }
    tot[u]=max(tot[u],sum-tot[u]);
    if(tot[u]<tot[root])root=u;
    return;
}

inline ll qpow(ll x,ll y){
    ll ans=1;
    while(y){
        if(y&1)ans=ans*x%k;
        x=x*x%k;
        y>>=1;
    }
    return ans;
}

inline void getdis(ll u,ll fa,ll sum1,ll sum2,ll dep){
    stk[++top].sum1=sum1;
    stk[top].sum2=sum2;
    stk[top].dep=dep;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getdis(v,u,(sum1*10+e[i].w)%k,(sum1+qpow(10,dep)*e[i].w)%k,dep+1);
    }
    return;
}

inline void exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return;
}

inline ll getnow(ll l,ll r){
    ll sum=0;
    if(l>r)return sum;
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]++;
    }
    for(ll i=l;i<=r;i++){
        ll x,y;
        exgcd(qpow(10,stk[i].dep),k,x,y);
        x=(x%k+k)%k;
        // cout<<qpow(10,stk[i].dep)<<" "<<x<<endl;
        sum+=dis[((k-stk[i].sum1*x%k)%k+k)%k];
    }
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]--;
    }
    return sum;
}
//sum2*qpow(10,sum1_dep)+sum1=0
//sum2+sum1*qpow(10,-sum1_dep)=0
inline void getans(ll u){
    top=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        ll last=top;
        getdis(v,u,e[i].w%k,e[i].w%k,1);
        ans-=getnow(last+1,top);
    }
    ans+=getnow(1,top);
    // cout<<u<<" ";
    for(ll i=1;i<=top;i++){
        if(!stk[i].sum1)ans++;
        if(!stk[i].sum2)ans++;
        // cout<<stk[i].sum1<<" "<<stk[i].sum2<<" "<<stk[i].dep<<endl;
    }
    // cout<<ans<<endl;
    return;
}

inline void getall(ll u){
    getans(u);
    vis[u]=true;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        root=0;
        sum=son[v];
        getrt(v,u);
        getall(root);
    }
    return;
}

int main(){
    n=read();k=read();
    // n=100000;k=11;
    for(ll i=1;i<n;i++){
        l=read()+1;r=read()+1;w=read();
        add(l,r,w);
        add(r,l,w);
        // add(i,i+1,1);
        // add(i+1,i,1);
    }
    tot[0]=1e9;
    sum=n;
    root=0;
    getrt(1,0);
    getall(root);
    writeln(ans);
    return 0;
}


#include <bits/stdc++.h>

#define ll long long
#define Max 100005

using namespace std;

inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline ll read(){
    ll x=0;char ch=gc();bool positive=1;
    for(;!isdigit(ch);ch=gc())if(ch=='-')positive=0;
    for(;isdigit(ch);ch=gc())x=x*10+ch-'0';
    return positive?x:-x;
}

inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}

inline void writeln(ll x){
    write(x);puts("");
}

struct Edge{
    ll v,to,w;
}e[Max*2];

struct Node{
    ll sum1,sum2,dep;
}stk[Max];

ll n,k,l,r,w,sum,ans,top,root,size,son[Max],tot[Max],head[Max];
bool vis[Max];
map<int,int>dis;

inline void add(ll u,ll v,ll w){
    e[++size].v=v;e[size].to=head[u];e[size].w=w;head[u]=size;
}

inline void getrt(ll u,ll fa){
    son[u]=1;
    tot[u]=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getrt(v,u);
        son[u]+=son[v];
        tot[u]=max(tot[u],son[v]);
    }
    tot[u]=max(tot[u],sum-tot[u]);
    if(tot[u]<tot[root])root=u;
    return;
}

inline ll qpow(ll x,ll y){
    ll ans=1;
    while(y){
        if(y&1)ans=ans*x%k;
        x=x*x%k;
        y>>=1;
    }
    return ans;
}

inline void getdis(ll u,ll fa,ll sum1,ll sum2,ll dep){
    stk[++top].sum1=sum1;
    stk[top].sum2=sum2;
    stk[top].dep=dep;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getdis(v,u,(sum1*10+e[i].w)%k,(sum1+qpow(10,dep)*e[i].w)%k,dep+1);
    }
    return;
}

inline ll getnow(ll l,ll r){
    ll sum=0;
    if(l>r)return sum;
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]++;
    }
    for(ll i=l;i<=r;i++){
        sum+=dis[(k-stk[i].sum1)*qpow(qpow(10,stk[i].dep),k-2)%k];
    }
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]--;
    }
    return sum;
}

inline void getans(ll u){
    top=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        ll last=top;
        getdis(v,u,e[i].w%k,e[i].w%k,1);
        ans-=getnow(last+1,top);
    }
    ans+=getnow(1,top);
    // cout<<u<<endl;
    for(ll i=1;i<=top;i++){
        if(!stk[i].sum1)ans++;
        if(!stk[i].sum2)ans++;
        // cout<<stk[i].sum1<<" "<<stk[i].sum2<<" "<<stk[i].dep<<endl;
    }
    return;
}

inline void getall(ll u){
    getans(u);
    vis[u]=true;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        root=0;
        sum=son[v];
        getrt(v,u);
        getall(root);
    }
    return;
}

int main(){
    n=read();k=read();
    for(ll i=1;i<n;i++){
        l=read()+1;r=read()+1;w=read();
        add(l,r,w);
        add(r,l,w);
    }
    tot[0]=1e9;
    sum=n;
    root=0;
    getrt(1,0);
    getall(root);
    writeln(ans);
    return 0;
}


#include <bits/stdc++.h>

#define ll long long
#define Max 100005

using namespace std;

inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline ll read(){
    ll x=0;char ch=gc();bool positive=1;
    for(;!isdigit(ch);ch=gc())if(ch=='-')positive=0;
    for(;isdigit(ch);ch=gc())x=x*10+ch-'0';
    return positive?x:-x;
}

inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}

inline void writeln(ll x){
    write(x);puts("");
}

struct Edge{
    ll v,to,w;
}e[Max*2];

struct Node{
    ll sum1,sum2,dep;
}stk[Max];

ll n,k,l,r,w,sum,ans,top,root,size,son[Max],tot[Max],head[Max];
bool vis[Max];
map<int,int>dis;

inline void add(ll u,ll v,ll w){
    e[++size].v=v;e[size].to=head[u];e[size].w=w;head[u]=size;
}

inline void getrt(ll u,ll fa){
    son[u]=1;
    tot[u]=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getrt(v,u);
        son[u]+=son[v];
        tot[u]=max(tot[u],son[v]);
    }
    tot[u]=max(tot[u],sum-tot[u]);
    if(tot[u]<tot[root])root=u;
    return;
}

inline ll qpow(ll x,ll y){
    ll ans=1;
    while(y){
        if(y&1)ans=ans*x%k;
        x=x*x%k;
        y>>=1;
    }
    return ans;
}

inline void getdis(ll u,ll fa,ll sum1,ll sum2,ll dep){
    stk[++top].sum1=sum1;
    stk[top].sum2=sum2;
    stk[top].dep=dep;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getdis(v,u,(sum1*10+e[i].w)%k,(sum1+qpow(10,dep)*e[i].w)%k,dep+1);
    }
    return;
}

inline void exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return;
}

inline ll getnow(ll l,ll r){
    ll sum=0;
    if(l>r)return sum;
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]++;
    }
    for(ll i=l;i<=r;i++){
        ll x,y;
        exgcd(qpow(10,stk[i].dep),k,x,y);
        x=(x%k+k)%k;
        // cout<<qpow(10,stk[i].dep)<<" "<<x<<endl;
        sum+=dis[(k-stk[i].sum1)*x%k];
    }
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]--;
    }
    return sum;
}

inline void getans(ll u){
    top=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        ll last=top;
        getdis(v,u,e[i].w%k,e[i].w%k,1);
        ans-=getnow(last+1,top);
    }
    ans+=getnow(1,top);
    // cout<<u<<" ";
    for(ll i=1;i<=top;i++){
        if(!stk[i].sum1)ans++;
        if(!stk[i].sum2)ans++;
        // cout<<stk[i].sum1<<" "<<stk[i].sum2<<" "<<stk[i].dep<<endl;
    }
    // cout<<ans<<endl;
    return;
}

inline void getall(ll u){
    getans(u);
    vis[u]=true;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        root=0;
        sum=son[v];
        getrt(v,u);
        getall(root);
    }
    return;
}

int main(){
    n=read();k=read();
    for(ll i=1;i<n;i++){
        l=read()+1;r=read()+1;w=read();
        add(l,r,w);
        add(r,l,w);
    }
    tot[0]=1e9;
    sum=n;
    root=0;
    getrt(1,0);
    getall(root);
    writeln(ans);
    return 0;
}


#include <bits/stdc++.h>

#define ll long long
#define Max 100005

using namespace std;

inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline ll read(){
    ll x=0;char ch=gc();bool positive=1;
    for(;!isdigit(ch);ch=gc())if(ch=='-')positive=0;
    for(;isdigit(ch);ch=gc())x=x*10+ch-'0';
    return positive?x:-x;
}

inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}

inline void writeln(ll x){
    write(x);puts("");
}

struct Edge{
    ll v,to,w;
}e[Max*2];

struct Node{
    ll sum1,sum2,dep;
}stk[Max];

ll n,k,l,r,w,sum,ans,top,root,size,son[Max],tot[Max],head[Max];
bool vis[Max];
map<int,int>dis;

inline void add(ll u,ll v,ll w){
    e[++size].v=v;e[size].to=head[u];e[size].w=w;head[u]=size;
}

inline void getrt(ll u,ll fa){
    son[u]=1;
    tot[u]=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getrt(v,u);
        son[u]+=son[v];
        tot[u]=max(tot[u],son[v]);
    }
    tot[u]=max(tot[u],sum-tot[u]);
    if(tot[u]<tot[root])root=u;
    return;
}

inline ll qpow(ll x,ll y){
    ll ans=1;
    while(y){
        if(y&1)ans=ans*x%k;
        x=x*x%k;
        y>>=1;
    }
    return ans;
}

inline void getdis(ll u,ll fa,ll sum1,ll sum2,ll dep){
    stk[++top].sum1=sum1;
    stk[top].sum2=sum2;
    stk[top].dep=dep;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(v==fa||vis[v])continue;
        getdis(v,u,(sum1*10+e[i].w)%k,(sum1+qpow(10,dep)*e[i].w)%k,dep+1);
    }
    return;
}

inline void exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return;
}

inline ll getnow(ll l,ll r){
    ll sum=0;
    if(l>r)return sum;
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]++;
    }
    for(ll i=l;i<=r;i++){
        ll x,y;
        exgcd(qpow(10,stk[i].dep),k,x,y);
        sum+=dis[(k-stk[i].sum1)*x%k];
    }
    for(ll i=l;i<=r;i++){
        dis[stk[i].sum2]--;
    }
    return sum;
}

inline void getans(ll u){
    top=0;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        ll last=top;
        getdis(v,u,e[i].w%k,e[i].w%k,1);
        ans-=getnow(last+1,top);
    }
    ans+=getnow(1,top);
    // cout<<u<<endl;
    for(ll i=1;i<=top;i++){
        if(!stk[i].sum1)ans++;
        if(!stk[i].sum2)ans++;
        // cout<<stk[i].sum1<<" "<<stk[i].sum2<<" "<<stk[i].dep<<endl;
    }
    return;
}

inline void getall(ll u){
    getans(u);
    vis[u]=true;
    for(ll i=head[u];i;i=e[i].to){
        ll v=e[i].v;
        if(vis[v])continue;
        root=0;
        sum=son[v];
        getrt(v,u);
        getall(root);
    }
    return;
}

int main(){
    n=read();k=read();
    for(ll i=1;i<n;i++){
        l=read()+1;r=read()+1;w=read();
        add(l,r,w);
        add(r,l,w);
    }
    tot[0]=1e9;
    sum=n;
    root=0;
    getrt(1,0);
    getall(root);
    writeln(ans);
    return 0;
}