EntropyIncreaser

CF 418E Digit Tree

Dec 27th, 2017
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.45 KB | None | 0 0
  1. #include <cstdio>
  2. #include <cstring>
  3.  
  4. #include <algorithm>
  5. #include <map>
  6.  
  7. #define LOG(FMT...) // fprintf(stderr, "[LOG]: "FMT)
  8.  
  9. using namespace std;
  10.  
  11. typedef long long ll;
  12. typedef map<int, int> map_t;
  13. typedef map_t::iterator iter_t;
  14.  
  15. struct edge {
  16.     int v, w;
  17.     edge* next;
  18. };
  19.  
  20. const int N = 100010;
  21.  
  22. int n, p, ordcnt;
  23.  
  24. bool vis[N], cut[N];
  25. int ord[N], sum[N], mex[N], q[N], dep[N], digit[N], rdigit[N], rprod[N], prod[N];
  26.  
  27. edge* g[N];
  28.  
  29. void add_edge(int u, int v, int w);
  30. void calc_order(int u);
  31. void calc_sum(int u);
  32. void dfs(int u);
  33. ll calc(int u);
  34. int rev(int a);
  35. void ex_gcd(int a, int b, int& x, int& y);
  36.  
  37. int main() {
  38.     ll ans = 0;
  39.     scanf("%d%d", &n, &p);
  40.     for (int rep = 1; rep < n; ++rep) {
  41.         int u, v, w;
  42.         scanf("%d%d%d", &u, &v, &w);
  43.         add_edge(u, v, w);
  44.         add_edge(v, u, w);
  45.     }
  46.     prod[0] = 1;
  47.     rprod[0] = 1;
  48.     rprod[1] = rev(10);
  49.     for (int i = 1; i <= n; ++i)
  50.         prod[i] = 10LL * prod[i - 1] % p;
  51.     for (int i = 2; i <= n; ++i)
  52.         rprod[i] = (ll)rprod[1] * rprod[i - 1] % p;
  53.     calc_order(0);
  54.     memset(cut, 0, sizeof(cut));
  55.     for (int i = 0; i < n; ++i) {
  56.         int u = ord[i];
  57.         dep[u] = 0;
  58.         digit[u] = 0;
  59.         rdigit[u] = 0;
  60.         dfs(u);
  61.         ans += calc(u);
  62.         cut[u] = true;
  63.         for (edge* p = g[u]; p; p = p->next)
  64.             if (!cut[p->v])
  65.                 ans -= calc(p->v);
  66.         ans -= 1;
  67.         LOG("FINE %d: %lld\n", i, ans);
  68.     }
  69.     printf("%lld\n", ans);
  70.     return 0;
  71. }
  72.  
  73. int rev(int a) {
  74.     int x, y;
  75.     ex_gcd(a, p, x, y);
  76.     if (x < 0)
  77.         x += p;
  78.     return x;
  79. }
  80.  
  81. void ex_gcd(int a, int b, int&x, int& y) {
  82.     if (b == 0) {
  83.         x = 1;
  84.         y = 0;
  85.         return;
  86.     }
  87.     ex_gcd(b, a % b, y, x);
  88.     y -= a / b * x;
  89. }
  90.  
  91. ll calc(int u) {
  92.     int ql = 0, qr = 1;
  93.     ll ret = 0;
  94.     map_t mp;
  95.     q[0] = u;
  96.     while (ql < qr) {
  97.         int v = q[ql++];
  98.         vis[v] = true;
  99.         iter_t it = mp.find(rdigit[v]);
  100.         if (it != mp.end())
  101.             ++it->second;
  102.         else
  103.             mp.insert(make_pair(rdigit[v], 1));
  104.         for (edge* p = g[v]; p; p = p->next)
  105.             if (!vis[p->v] && !cut[p->v])
  106.                 q[qr++] = p->v;
  107.     }
  108.     for (int i = 0; i < qr; ++i)
  109.         vis[q[i]] = false;
  110.     for (int i = 0; i < qr; ++i) {
  111.         int key = (ll)-digit[q[i]] * rprod[dep[q[i]]] % p;
  112.         if (key < 0)
  113.             key += p;
  114.         iter_t it = mp.find(key);
  115.         if (it != mp.end()) {
  116.             LOG("%d FOUND %d WITH %d\n", q[i], it->second, it->first);
  117.             ret += it->second;
  118.         }
  119.     }
  120.     return ret;
  121. }
  122.  
  123. void dfs(int u) {
  124.     vis[u] = true;
  125.     for (edge* p = g[u]; p; p = p->next)
  126.         if (!vis[p->v] && !cut[p->v]) {
  127.             dep[p->v] = dep[u] + 1;
  128.             rdigit[p->v] = ((ll)prod[dep[u]] * p->w + rdigit[u]) % ::p;
  129.             digit[p->v] = (digit[u] * 10LL + p->w) % ::p;
  130.             dfs(p->v);
  131.         }
  132.     vis[u] = false;
  133. }
  134.  
  135. void calc_order(int u) {
  136.     calc_sum(u);
  137.     int s = sum[u], ql = 0, qr = 1;
  138.     q[0] = u;
  139.     while (ql < qr) {
  140.         int v = q[ql++];
  141.         vis[v] = true;
  142.         mex[v] = max(mex[v], s - sum[v]);
  143.         if (mex[v] < mex[u])
  144.             u = v;
  145.         for (edge* p = g[v]; p; p = p->next)
  146.             if (!vis[p->v] && !cut[p->v])
  147.                 q[qr++] = p->v;
  148.     }
  149.     for (int i = 0; i < qr; ++i)
  150.         vis[q[i]] = false;
  151.     ord[ordcnt++] = u;
  152.     cut[u] = true;
  153.     for (edge* p = g[u]; p; p = p->next)
  154.         if (!cut[p->v])
  155.             calc_order(p->v);
  156. }
  157.  
  158. void calc_sum(int u) {
  159.     vis[u] = true;
  160.     mex[u] = 0;
  161.     sum[u] = 1;
  162.     for (edge* p = g[u]; p; p = p->next)
  163.         if (!vis[p->v] && !cut[p->v]) {
  164.             calc_sum(p->v);
  165.             sum[u] += sum[p->v];
  166.             mex[u] = max(mex[u], sum[p->v]);
  167.         }
  168.     vis[u] = false;
  169. }
  170.  
  171. void add_edge(int u, int v, int w) {
  172.     static edge pool[N * 2];
  173.     static edge* p = pool;
  174.     ++p;
  175.     p->v = v;
  176.     p->w = w;
  177.     p->next = g[u];
  178.     g[u] = p;
  179. }
Advertisement
Add Comment
Please, Sign In to add comment