码迷,mamicode.com
首页 > 其他好文 > 详细

The Preliminary Contest for ICPC Asia Shenyang 2019

时间:2019-09-15 11:19:48      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:ons   答案   pac   blank   head   print   operator   style   路径   

The Preliminary Contest for ICPC Asia Shenyang 2019

Texas hold‘em Poker

#include <bits/stdc++.h>

using namespace std;

const int maxn=1e6+10;
int num[1000];
int shun(){
    for (int i=15;i>=5;i--){
        if (num[i]&&num[i-1]&&num[i-2]&&num[i-3]&&num[i-4]) return i;
    }
    return -1;
}
struct node {
    int rk, num1, num2, num3;
    string na;

    bool operator<(const node a) const {
        if (rk != a.rk) return rk > a.rk;
        if (num1 != a.num1) return num1 > a.num1;
        if (num2 != a.num2) return num2 > a.num2;
        if (num3 != a.num3) return num3 > a.num3;
        return na < a.na;
    }
}b[maxn];

int n;
string na,s;
unordered_map<string,int>ma;

int main() {
    //freopen("1.txt", "r", stdin);
    ma["A"] = 1;
    ma["2"] = 2;
    ma["3"] = 3;
    ma["4"] = 4;
    ma["5"] = 5;
    ma["6"] = 6;
    ma["7"] = 7;
    ma["8"] = 8;
    ma["9"] = 9;
    ma["10"] = 10;
    ma["J"] = 11;
    ma["Q"] = 12;
    ma["K"] = 13;
    while (cin >> n) {
        for (int i = 1; i <= n; i++) {
            cin >> na >> s;
            b[i].na = na;
            string ss;
            int len = s.length();
            for (int j = 0; j <= 15; j++) num[j] = 0;
            for (int j = 0; j < len; j++) {
                ss = "";
                if (s[j] != ‘1‘) ss = s[j];
                else {
                    ss = s[j];
                    ss = ss + s[j + 1];
                    j++;
                }
                num[ma[ss]]++;
            }
            if (num[10] && num[11] && num[12] && num[13] && num[1]) {
                b[i].rk = 8;
                b[i].num1 = b[i].num2 = b[i].num3 = 0;
                continue;
            }
            int k=shun();
            if (k!=-1) {
                b[i].rk = 7;
                b[i].num1 = k;
                continue;
            }

            int f4 = 0, kk;
            for (int j = 0; j <= 15; j++) {
                if (num[j] == 4) {
                    kk = j;
                    f4 = 1;
                    break;
                }
            }
            if (f4) {
                int kkk;
                for (int j = 0; j <= 15; j++) {
                    if (num[j] == 1) {
                        kkk = j;
                        break;
                    }
                }
                b[i].rk = 6;
                b[i].num1 = kk;
                b[i].num2 = kkk;
                b[i].num3 = 0;
                continue;
            }
            int f3 = 0;
            for (int j = 0; j <= 15; j++) {
                if (num[j] == 3) {
                    kk = j;
                    f3 = 1;
                    break;
                }
            }
            if (f3) {
                int kkk, f2 = 0;
                for (int j = 0; j <= 15; j++) {
                    if (num[j] == 2) {
                        kkk = j;
                        f2 = 1;
                        break;
                    }
                }
                if (f2) {
                    b[i].rk = 5;
                    b[i].num1 = kk;
                    b[i].num2 = kkk;
                    b[i].num3 = 0;
                    continue;
                }
                int sum = 0;
                for (int j = 0; j <= 15; j++) {
                    if (num[j] == 1) {
                        sum += j;
                    }
                }
                b[i].rk = 4;
                b[i].num1 = kk;
                b[i].num2 = sum;
                b[i].num3 = 0;
                continue;
            }
            kk = 0;
            for (int j = 0; j <= 15; j++) {
                if (num[j] == 2) {
                    kk++;
                }
            }
            if (kk == 2) {
                int mx = 0, mi = 10000, kkk;
                for (int j = 0; j <= 15; j++) {
                    if (num[j] == 2) {
                        mx = max(mx, j);
                        mi = min(mi, j);
                    }
                    if (num[j] == 1) {
                        kkk = j;
                    }
                }
                b[i].rk = 3;
                b[i].num1 = mx;
                b[i].num2 = mi;
                b[i].num3 = kkk;
                continue;
            }
            if (kk == 1) {
                int kkk, sum = 0;
                for (int j = 0; j <= 15; j++) {
                    if (num[j] == 2) {
                        kkk = j;
                    } else if (num[j]) sum += j;
                }
                b[i].rk = 2;
                b[i].num1 = kkk;
                b[i].num2 = sum;
                b[i].num3 = 0;
                continue;
            }
            int sum = 0;
            for (int j = 0; j <= 15; j++) {
                if (num[j]) sum += j;
            }
            b[i].rk = 1;
            b[i].num1 = sum;
            b[i].num2 = 0;
            b[i].num3 = 0;
        }
        sort(b + 1, b + n + 1);
        for (int i = 1; i <= n; i++) {
            cout << b[i].na << endl;
        }
    }
    return 0;
}

Fish eating fruit

题意:求一颗树中所有点对(a,b)的路径长度,路径长度按照模3之后的值进行分类,最后分别求每一类的和

分析:树形DP

dp[i][j]表示以 i 为根的子树中,所有子节点到 i 的路径长度模3等于 j 的路径之和

c[i][j]表示以 i 为根的子树中,所有子节点到 i 的路径长度模3等于 j 的点数

ok[i][j]表示以 i 为根的子树中,是否有子节点到 i 的路径长度模3等于 j

每次只考虑所有经过根 x 的路径,并且路径的一个端点在 x 的一颗子树上,另一个端点在 x 的另一颗子树上。(可以想到其他所有情况都可以在考虑 x 的子树结点或者是x的祖先结点时被考虑到)
假设当前枚举到 x 的子节点 y,之前遍历的子节点已经使得三个数组更新。那么我们假设要计算的路径的起点在 y ,要计算的路径的终点在之前遍历过的子节点中。

计算答案贡献:
关于x-y的连边的贡献为

c[x][a]*c[y][b]*edge

关于起点到 y 的所有路径长度的贡献为

c[x][a]*dp[y][b]

关于x到终点的所有路径长度的贡献为

c[y][b]*dp[x][a]

最终边权所属分类为(a+b+edge)%3累加到答案即可

关于更新 x

用 y 来更新 x

dp[x][(a+edge)%3]+=dp[y][a]+edgec[y][a]

ok[x][(a+edge)%3]=true

c[x][(a+edge)%3]+=c[y][a]

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn=10020;
const int maxm=200010;
const ll mod=1e9+7;

int t,head[maxn];
struct edge{
    int v,next;
    ll w;
}e[maxm];
bool ok[maxn][3];
int n;
ll dp[maxn][3],c[maxn][3],ans[3];

void add(int u,int v,int w) {
    t++;
    e[t].v = v;
    e[t].w = w;
    e[t].next = head[u];
    head[u] = t;
}

void dfs(int u,int fa) {
    for (int i = head[u]; i; i = e[i].next) {
        int v = e[i].v;
        if (v == fa) continue;
        dfs(v, u);
        ll w = e[i].w;
        for (int j = 0; j < 3; j++) {
            for (int k = 0; k < 3; k++) {
                if (ok[u][j] && ok[v][k]) {
                    ans[(j + k + w) % 3] += (dp[u][j] * c[v][k] % mod + dp[v][k] * c[u][j] % mod) % mod;
                    ans[(j + k + w) % 3] += w * c[u][j] % mod * c[v][k] % mod;
                    ans[(j + k + w) % 3] %= mod;
                }
            }
        }
        for (int j = 0; j < 3; j++) {
            if (ok[v][j]) {
                dp[u][(j + w) % 3] += dp[v][j] + w * c[v][j] % mod;
                dp[u][(j + w) % 3] %= mod;
                c[u][(j + w) % 3] += c[v][j];
                ok[u][(j + w) % 3] = 1;
            }
        }
    }
}

int main() {
    while (~scanf("%d", &n)) {
        t=0;
        for (int i = 1; i <= n; i++) {
            dp[i][0] = dp[i][1] = dp[i][2] = 0;
            c[i][1] = c[i][2] = 0;
            c[i][0] = 1;
            ok[i][0] = 1;
            ok[i][1] = ok[i][2] = 0;
            head[i] = 0;
            ans[0]=ans[1]=ans[2]=0;
        }
        for (int i = 1, u, v,w; i < n; i++) {
            scanf("%d%d%d", &u, &v, &w);
            u++;
            v++;
            add(u, v, w);
            add(v, u, w);
        }
        dfs(1, 0);
        printf("%lld %lld %lld\n", ans[0] * 2 % mod, ans[1] * 2 % mod, ans[2] * 2 % mod);
    }
    return 0;
}

 

  

 

The Preliminary Contest for ICPC Asia Shenyang 2019

标签:ons   答案   pac   blank   head   print   operator   style   路径   

原文地址:https://www.cnblogs.com/Accpted/p/11521281.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!