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]+edge∗c[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;
}

  

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

时间: 2024-10-07 09:01:17

The Preliminary Contest for ICPC Asia Shenyang 2019的相关文章

C:Dawn-K&#39;s water (The Preliminary Contest for ICPC Asia Shenyang 2019)

Dawn-K recently discovered a very magical phenomenon in the supermarket of Northeastern University: The large package is not necessarily more expensive than the small package. On this day, Dawn-K came to the supermarket to buy mineral water, he found

The Preliminary Contest for ICPC Asia Shenyang 2019 H. Texas hold&#39;em Poker

题目链接:https://nanti.jisuanke.com/t/41408 题目意思很简单,就是个模拟过程. 1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 #include <map> 6 #define rep(i,j,k) for(int i = (j); i <= (k); ++i) 7 #define

The Preliminary Contest for ICPC Asia Shenyang 2019 F. Honk&#39;s pool

题目链接:https://nanti.jisuanke.com/t/41406 思路:如果k的天数足够大,那么所有水池一定会趋于两种情况: ① 所有水池都是一样的水位,即平均水位 ② 最高水位的水池和最低水位的水池高度只相差一个高度,且最低水位一定是平均水位 如果k给了个限制: 我们当然需要先算出所有水池高度的平均值. 然后从低到高排序,二分小于平均值的水位,二分高于平均值的水位, 然后判断二分的预期值需要的天数是否小于等于k.然后二分找出最低水位的最大值, 最高水位的最小值,两者相减就是答案了

The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力)

The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力) 传送门:https://nanti.jisuanke.com/t/41400 题意: 给你三个数组a,b,c,要你求有多少个三元组(i,j,k),使得 \[ \begin{array}{l}{\left|A_{i}-B_{j}\right| \leq C_{k}, \text { and }} \\ {\left|B_{j}-C_{k}\right| \leq

The Preliminary Contest for ICPC Asia Nanjing 2019/2019南京网络赛——题解

(施工中……) 比赛传送门:https://www.jisuanke.com/contest/3004 D. Robots(期望dp) 题意 给一个DAG,保证入度为$0$的点只有$1$,出度为$0$的点只有$n$. 现在一个机器人从$1$出发,每天都会以相同的概率前往相邻节点之一或静止不动. 每天机器人消耗的耐久等于经过的天数. 求机器人到点$n$期望消耗的耐久. 划水划的很愉快,唯一一道做出来的题.但是和题解做法不同(感觉我的方法麻烦),因此砸了3h在这题上面(正在试图读懂题解ing). 设

The Preliminary Contest for ICPC Asia Nanjing 2019 D. Robots(概率dp)

题目链接:https://nanti.jisuanke.com/t/41301 题目大意: 给定一个没有循环的有向图,它从节点1开始,到节点n结束. 有一个机器人从1开始,每天都会以相同的概率前往相邻节点之一或静止不动.每天机器人的耐久性消耗量等于经过的天数. 请计算机器人到达节点n时的预期耐久性消耗量. 保证只有一个节点(节点1)的in-degree等于00,并且只有一个节点(节点n)的out-degree等于0.并且图中没有多个边缘. 解题思路: 设dp[i]为从i到达终点n的期望时间那么很

The Preliminary Contest for ICPC Asia Xuzhou 2019

A What is better? 推不出来,写个程序打表,用扩展中国剩余定理合并,居然会溢出longlong,还好不会溢出__int128(赛后exit(-1)测试),实际证明溢出返回-1是不靠谱的,毕竟后面可以又把它搞小了. #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef __int128 lll; const int MAXK = 10 + 5; void exgcd(lll a, ll

The Preliminary Contest for ICPC Asia Shanghai 2019

D. Counting Sequences I 暴力搜索. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1000000007; map<vector<short>, short> m; vector<short> vec; void calc(int num1) { vector<short> tmp; if(num1) t

Digit sum-----The Preliminary Contest for ICPC Asia Shanghai 2019

A digit sum S_b(n)Sb?(n) is a sum of the base-bb digits of nn. Such as S_{10}(233) = 2 + 3 + 3 = 8S10?(233)=2+3+3=8, S_{2}(8)=1 + 0 + 0 = 1S2?(8)=1+0+0=1, S_{2}(7)=1 + 1 + 1 = 3S2?(7)=1+1+1=3. Given NN and bb, you need to calculate \sum_{n=1}^{N} S_b