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