• [Codeforces 715C] Digit Tree


    [题目链接]

             https://codeforces.com/contest/715/problem/C

    [算法]

            考虑点分治 

            一条路径(x , y)合法当且仅当 : d(x) * 10 ^ dep(x) + d(y) = 0(mod m) , 其中d(u)表示u到分治重心路径上数字拼接起来所形成的数

            统计答案时 , 我们只需维护一个map , 维护10 ^ -dep(u) * d(u) (mod m)

            然后计算每个点的贡献即可

            时间复杂度 : O(NlogN ^ 2)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100010
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    struct edge
    {
            int to , w , nxt;
    } e[N << 1];
    
    int n , m , tot , len , root;
    ll ans;
    int pw[N] , head[N] , size[N] , weight[N] , D[N] , depth[N];
    bool visited[N];
    map<int , int> mp;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v , int w)
    {
            ++tot;
            e[tot] = (edge){v , w , head[u]};
            head[u] = tot;
    }
    inline void getroot(int u , int par , int total)
    {
            size[u] = 1;
            weight[u] = 0;
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == par || visited[v]) continue;
                    getroot(v , u , total);
                    size[u] += size[v];
                    chkmax(weight[u] , size[v]);    
            }        
            chkmax(weight[u] , total - size[u]);
            if (weight[u] < weight[root]) root = u;
    }
    inline void exgcd(int a , int b , int &x , int &y)
    {
            if (b == 0)
            {
                    x = 1;
                    y = 0;
            } else
            {
                    exgcd(b , a % b , y , x);
                    y -= a / b * x;
            }
    }
    inline int inv(int a)
    {
            int x , y;
            exgcd(a , m , x , y);
            return (x % m + m) % m;
    }
    inline void dfs(int u , int par , int d1 , int d2)
    {
            if (depth[u] > 0) ++mp[(1ll * d2 % m * inv(pw[depth[u]] % m)) % m];
            D[++len] = d1;
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to , w = e[i].w;
                    if (v == par || visited[v]) continue;
                    depth[v] = depth[u] + 1;
                    dfs(v , u , (1ll * w * pw[depth[v] - 1] % m + d1) % m , (10ll * d2 % m + w) % m);
            }
    }
    inline ll calc(int u , int d)
    {
            mp.clear();
            len = 0;
            if (!d) dfs(u , -1 , 0 , 0);
            else dfs(u , -1 , d % m , d % m);
            ll res = 0;
            for (int i = 1; i <= len; ++i)
            {
                    int goal = ((m - D[i]) % m + m) % m;
                    res += (ll)mp[goal];
                    if (!d && !D[i]) ++res;
            }
            return res;
    }
    inline void work(int u)
    {
            visited[u] = true;
            depth[u] = 0;
            ans += calc(u , 0);
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to , w = e[i].w;
                    if (visited[v]) continue;
                    depth[v] = 1;
                    ans -= calc(v , w);
            }
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (visited[v]) continue;
                    root = 0;
                    getroot(v , u , size[v]);
                    work(root);
            }
    }
    
    int main()
    {
            
            read(n); read(m);
            pw[0] = 1;
            for (int i = 1; i <= n; ++i) pw[i] = 1ll * pw[i - 1] * 10 % m;
            for (int i = 1; i < n; ++i)
            {
                    int u , v , w;
                    read(u); read(v); read(w);
                    ++u; ++v;
                    addedge(u , v , w);
                    addedge(v , u , w);
            }
            weight[0] = n;
            root = 0;
            getroot(1 , 0 , n);
            work(root);
            ans -= n;
            printf("%I64d
    " , ans);
            
            return 0;
        
    }

            

            

  • 相关阅读:
    Kettle学习(2)
    kettle学习(1)
    Quartz在Spring中的使用
    JVM垃圾收集简介
    快速排序

    20190827最新论文
    GNN
    Multimodal Machine Learning
    Wasserstein距离 及两多元高斯分布间的W距离
  • 原文地址:https://www.cnblogs.com/evenbao/p/10544912.html
Copyright © 2020-2023  润新知