• [树上DP] I 2019 P2634 [国家集训队]聪聪可可


    求树上简单路径长度为2019倍数的路径条数


     解题思路 :

    二维状态dp[i][j]代表i节点的子树上所有点到i的距离为j的个数

    考虑两点u, v,两点间的贡献为  ans += dp[u][i] * dp[v][(2019 - i - v + 2019) % 2019]; i = 0 - 2018

    此时u的贡献会转移为 dp[u][(i + val(边权)) % 2019] += dp[v][i]; i = 0 - 2018

    所以计算u v时 v的子树必须计算完成 所以递归计算

    对于洛谷P2634 考虑两点和自身点 总答案为上dp计算答案*2+点数即可

    /*
        Zeolim - An AC a day keeps the bug away
    */
      
    //#pragma GCC optimize(2)
    //#pragma GCC ("-W1,--stack=128000000")
    #include <bits/stdc++.h>
    using namespace std;
    #define mp(x, y) make_pair(x, y)
    #define fr(x, y, z) for(int x = y; x < z; ++x)
    #define pb(x) push_back(x)
    #define mem(x, y) memset(x, y, sizeof(x))
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    typedef std::pair <int, int> pii;
    typedef std::vector <int> vi;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f;
    const ll MOD = 386910137;
    const ull P = 13331;
    const int MAXN = 2e5 + 10;
     
    int head[MAXN] = {0}, cnt = 0;
    struct node { int to, val, next; }edge[MAXN];
    void add(int from, int to, int val) { edge[++cnt] = node{to, val, head[from]}; head[from] = cnt; }
    int dp[MAXN][2030];
    int ans = 0;
     
    void init(int n)
    {
        cnt = 0;
        fill(head, head + n + 10, 0);
        for(int i = 1; i <= n; ++i)
            fill(dp[i], dp[i] + 2030, 0);
        ans = 0;
    }
     
    void cal(int now, int fa, int v)
    {
        for(int i = 0; i < 2019; ++i)
            ans += dp[fa][i] * dp[now][(2019 - i - v + 2019) % 2019];
             
        for(int i = 0; i < 2019; ++i)
            dp[now][(i + v) % 2019] += dp[fa][i];
    }
      
    void gao(int now, int fa)
    {  
        dp[now][0] = 1;
         
        for(int it = head[now]; it; it = edge[it].next)
        {
            int to = edge[it].to, v = edge[it].val;
             
            if(to == fa)
                continue;
             
            gao(to, now);
             
            cal(now, to, v);   
        }  
    }
     
    int main()
    { 
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        //freopen("d:out.txt","w",stdout);
        //freopen("d:in.txt","r",stdin);
         
        int n;
         
        while(cin >> n)
        {
            init(n);
            for(int i = 1, x, y, z; i < n; ++i)
            {
                cin >> x >> y >> z;
                add(x, y, z);
                add(y, x, z);
            }
            ans = 0;
            gao(1, 0);
            cout << ans << '
    ';
        }
     
        return 0;
    }
  • 相关阅读:
    Window 下配置ChromeDriver(简单4步完成)[转]
    selenium之 chromedriver与chrome版本映射表(更新至v2.46)[转]
    学习网站
    如何理解python中的类和方法(转)
    面试题整理20191127
    mysql 慢查询
    python学习--代码组织实例
    ubuntu下安装Matlab
    SkinPP for VC
    C++中的4个类型转换关键字
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270331.html
Copyright © 2020-2023  润新知