The Preliminary Contest for ICPC Asia Shenyang 2019

Posted accpted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了The Preliminary Contest for ICPC Asia Shenyang 2019相关的知识,希望对你有一定的参考价值。

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的主要内容,如果未能解决你的问题,请参考以下文章

The Preliminary Contest for ICPC Asia Yinchuan 2019

The Preliminary Contest for ICPC Asia Shenyang 2019

The Preliminary Contest for ICPC Asia Shanghai 2019

The Preliminary Contest for ICPC Asia Shanghai 2019

The Preliminary Contest for ICPC Asia Xuzhou 2019

The Preliminary Contest for ICPC Asia Nanchang 2019