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]+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;
以上是关于The Preliminary Contest for ICPC Asia Shenyang 2019的主要内容,如果未能解决你的问题,请参考以下文章