Atcoder CODE FESTIVAL 2017 Final 简要题解
来源:互联网 发布:电脑软件搬家 编辑:程序博客网 时间:2024/06/05 23:56
AKIBA
模拟。
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}string s, t;int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif cin >> s; for (int i = 0; i < s.length(); t.pb(s[i ++])) if ((s[i] == 'K' || s[i] == 'B' || s[i] == 'R') && (!i || s[i - 1] != 'A')) t.pb('A'); if (t.back() != 'A') t.pb('A'); return puts(t == "AKIHABARA" ? "YES" : "NO"), 0;}
Palindrome-phobia
最后一定是”abcabc”的形式,那么最大出现次数减去最小出现次数不超过
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 100005;char s[MAXN];int a[3];int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif scanf("%s", s); for (int i = 0; s[i]; i ++) a[s[i] - 'a'] ++; return puts(*max_element(a, a + 3) - *min_element(a, a + 3) <= 1 ? "YES" : "NO"), 0;}
Time Gap
如果i出现
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 55;int n, ans, cnt[MAXN];bool v[MAXN];inline void DFS(int x){ if (x == 13) { int ret = 24; for (int i = 0; i < 24; i ++) for (int j = i + 1; j < 24; j ++) if (v[i] && v[j]) ret = min(ret, min(j - i, 24 - j + i)); ans = max(ans, ret); return ; } if (cnt[x] == 2) v[x] = v[24 - x] = 1, DFS(x + 1); else if (cnt[x]) { v[x] = 1, DFS(x + 1), v[x] = 0; if (x) v[24 - x] = 1, DFS(x + 1), v[24 - x] = 0; } else DFS(x + 1);}int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif n = Read(); for (int i = 1; i <= n; i ++) cnt[Read()] ++; cnt[0] ++; for (int i = 1; i < 12; i ++) if (cnt[i] > 2) return puts("0"), 0; if (cnt[12] > 1 || cnt[0] > 1) return puts("0"), 0; DFS(0); return printf("%d\n", ans), 0;}
Zabuton
考虑确定一个顺序之后DP,不难发现顺序就是
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 5005;struct Node{ int p, h; bool operator < (const Node &b) const { return p + h < b.p + b.h; }} a[MAXN];LL f[MAXN];int n;int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif n = Read(); for (int i = 1; i <= n; i ++) a[i].h = Read(), a[i].p = Read(), f[i] = 1LL << 60; sort(a + 1, a + n + 1); for (int i = 1; i <= n; i ++) for (int j = i; j; j --) if (f[j - 1] <= a[i].h) f[j] = min(f[j], f[j - 1] + a[i].p); for (int i = n; ~i; i --) if (f[i] ^ 1LL << 60) return printf("%d\n", i), 0;}
Combination Lock
考虑差分,那么每次相当于给
一个连通块模
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 100005;int n, m, a[MAXN], b[MAXN], f[MAXN];char s[MAXN];inline int Find(int x){ while (x ^ f[x]) x = f[x] = f[f[x]]; return x;}int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif scanf("%s", s + 1), n = strlen(s + 1), m = Read(); for (int i = 1; i <= n; i ++) a[i] = s[i] - 'a'; for (int i = n + 1; i; i --) f[i] = i, a[i] = (a[i] - a[i - 1] + 26) % 26; for (int i = 1, l, r; i <= m; i ++) l = Read(), r = Read(), f[Find(l)] = Find(r + 1); for (int i = 1; i <= n + 1; i ++) f[Find(i)] = Find(n + 2 - i); for (int i = 1; i <= n + 1; i ++) b[Find(i)] = (b[Find(i)] + a[i]) % 26; for (int i = 1; i <= n + 1; i ++) if (Find(i) == i && b[i]) return puts("NO"), 0; return puts("YES"), 0;}
Distribute Numbers
考虑相等数的对数,不难得出
然后打表求出小范围解,大范围的类似构造一下。
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 50;int k = 38, n = k * (k - 1) + 1, a[MAXN][MAXN];int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif printf("%d %d\n", n, k); for (int i = 1; i <= k; i ++) { printf("1"); for (int j = (i - 1) * (k - 1) + 2; j <= i * (k - 1) + 1; j ++) printf(" %d", j), a[i][j - (i - 1) * (k - 1) - 2] = j; putchar(10); } for (int i = 0; i < k - 1; i ++) for (int j = 0; j < k - 1; j ++) { printf("%d", i + 2); for (int l = 2, cur = j; l <= k; l ++, cur = (cur + i) % (k - 1)) printf(" %d", a[l][cur]); putchar(10); }}
Mancala
最优策略一定是每次选最左边的符合要求的位置。
记
把这个过程DP掉。
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 105;const int MAXM = 3505;const int mod = 1e9 + 7;int n, m, ret, lst, f[MAXN][MAXM];int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif n = Read(), m = Read(); ret = n * m * (m + 1) / 2; for (int i = 1; i < n; i ++) ret = 1LL * ret * (m + 1) % mod; f[n + 1][0] = 1; for (int i = n; i; lst += (lst + min(i, m)) / i, i --) for (int j = 0; j <= lst; j ++) for (int k = 0; k <= m; k ++) if (k <= i) f[i][j + (j + k) / i] = (f[i][j + (j + k) / i] + f[i + 1][j]) % mod; else f[i][j] = (f[i][j] + f[i + 1][j]) % mod; for (int i = 1; i <= lst; i ++) ret = (ret - 1LL * f[1][i] * i % mod + mod) % mod; return printf("%d\n", ret), 0;}
Poor Penguin
如果一个位置左上或者左下或者右上或者右下没有冰山,那么这个位置就会坏掉。
还有一种情况是存在一条横线和一条竖线将这里分成四部分,左上右下没有冰山或者右上左下没有冰山,那么两部分就变成了独立的了,可以看题解的图来帮助理解。
DP矩形的四个边界。
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 45;const int INF = 0x3f3f3f3f;int n, m, xp, yp, ans, s[MAXN][MAXN], f[MAXN][MAXN][MAXN][MAXN];char a[MAXN][MAXN];inline int Sum(int xl, int xr, int yl, int yr){ return s[xr][yr] + s[xl - 1][yl - 1] - s[xl - 1][yr] - s[xr][yl - 1];}int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif n = Read(), m = Read(), mset(f, INF), ans = INF; for (int i = 1; i <= n; i ++) scanf("%s", a[i] + 1); for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) if (a[i][j] == 'P') xp = i, yp = j; for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) s[i][j] = s[i - 1][j] + s[i][j - 1] + (a[i][j] == '#') - s[i - 1][j - 1]; f[1][n][1][m] = 0; for (int xl = 1; xl <= n; xl ++) for (int xr = n; xr >= xl; xr --) for (int yl = 1; yl <= m; yl ++) for (int yr = m; yr >= yl; yr --) if (f[xl][xr][yl][yr] ^ INF) { int cur = f[xl][xr][yl][yr], val; if (xl <= xp && xp <= xr && yl <= yp && yp <= yr) ans = min(ans, cur + min(min(Sum(xl, xp, yl, yp), Sum(xl, xp, yp, yr)), min(Sum(xp, xr, yl, yp), Sum(xp, xr, yp, yr)))); else ans = min(ans, cur); cur += Sum(xl, xr, yl, yr); for (int x = xl; x <= xr + 1; x ++) for (int y = yl; y <= yr + 1; y ++) if (!((x == xl || x == xr + 1) && (y == yl || y == yr + 1))) { val = Sum(xl, x - 1, yl, y - 1) + Sum(x, xr, y, yr); if (x > xl && y > yl && !(x <= xp && xp <= xr && y <= yp && yp <= yr)) f[xl][x - 1][yl][y - 1] = min(f[xl][x - 1][yl][y - 1], cur - val); if (x <= xr && y <= yr && !(xl <= xp && xp < x && yl <= yp && yp < y)) f[x][xr][y][yr] = min(f[x][xr][y][yr], cur - val); val = Sum(xl, x - 1, y, yr) + Sum(x, xr, yl, y - 1); if (x > xl && y <= yr && !(x <= xp && xp <= xr && yl <= yp && yp < y)) f[xl][x - 1][y][yr] = min(f[xl][x - 1][y][yr], cur - val); if (x <= xr && y > yl && !(xl <= xp && xp < x && y <= yp && yp <= yr)) f[x][xr][yl][y - 1] = min(f[x][xr][yl][y - 1], cur - val); } } return printf("%d\n", ans), 0;}
Full Tournament
对于一组
不妨设
这相当于存在一个拓扑序关系,求出每个
最后把
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 262145;int n, N, R[MAXN], low[MAXN], hig[MAXN], val[MAXN];priority_queue <pii, vector <pii>, greater <pii>> q;vector <pii> eve[MAXN];int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif n = Read(), N = 1 << n; for (int i = 1; i < N; i ++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << n - 1); for (int i = 0; i < N; i ++) val[i] = Read() - 1; for (int i = N - 1; ~i; i --) { hig[i] = N - 1; if (~val[i]) hig[i] = val[i]; for (int j = 0; j < n; j ++) if (!(i >> j & 1)) hig[i] = min(hig[i], hig[i ^ 1 << j]); } for (int i = 0; i < N; i ++) { low[i] = 0; if (~val[i]) low[i] = val[i]; for (int j = 0; j < n; j ++) if (i >> j & 1) low[i] = max(low[i], low[i ^ 1 << j]); } for (int i = 0; i < N; i ++) if (low[i] > hig[i]) return puts("NO"), 0; else eve[low[i]].pb(mp(hig[i], i)); for (int i = 0; i < N; i ++) { for (auto e : eve[i]) q.push(e); if (q.empty() || q.top().xx < i) return puts("NO"), 0; val[q.top().yy] = i, q.pop(); } puts("YES"); for (int i = 0; i < N; i ++) printf("%d%c", val[R[i]] + 1, i == N - 1 ? '\n' : ' '); return 0;}
Tree MST
直接点分,每个子树连
#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){ int x = 0, f = 1, c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -1; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; return x * f;}const int MAXN = 200005;struct Edge{ int u, v; LL w; bool operator < (const Edge &b) const { return w < b.w; }};int n, a[MAXN], f[MAXN], siz[MAXN];vector <pii> adj[MAXN];vector <Edge> edg;vector <int> seq;bool vis[MAXN];LL d[MAXN];inline int Find(int x){ while (x ^ f[x]) x = f[x] = f[f[x]]; return x;}inline void FindRoot(int x, int p, int Siz, int &c){ bool f = true; siz[x] = 1; for (auto e : adj[x]) if (!vis[e.xx] && (e.xx ^ p)) FindRoot(e.xx, x, Siz, c), f &= siz[e.xx] <= Siz >> 1, siz[x] += siz[e.xx]; f &= siz[x] >= Siz >> 1; if (f) c = x;}inline void FindSize(int x, int p){ seq.pb(x), siz[x] = 1; for (auto e : adj[x]) if (!vis[e.xx] && (e.xx ^ p)) d[e.xx] = d[x] + e.yy, FindSize(e.xx, x), siz[x] += siz[e.xx];}inline void Solve(int x, int Siz){ int c, p = 0; FindRoot(x, 0, Siz, c); vis[x = c] = true, d[x] = 0, seq.clear(); FindSize(x, 0); LL val = 1LL << 60; for (auto y : seq) if ((d[y] += a[y]) < val) val = d[y], p = y; for (auto y : seq) edg.pb({p, y, d[p] + d[y]}); for (auto e : adj[x]) if (!vis[e.xx]) Solve(e.xx, siz[e.xx]);}int main(){#ifdef wxh010910 freopen("data.in", "r", stdin);#endif n = Read(); for (int i = 1; i <= n; i ++) a[i] = Read(); for (int i = 1, x, y, w; i < n; i ++) x = Read(), y = Read(), w = Read(), adj[x].pb(mp(y, w)), adj[y].pb(mp(x, w)); Solve(1, n); sort(edg.begin(), edg.end()); for (int i = 1; i <= n; i ++) f[i] = i; LL ans = 0; for (auto e : edg) if (Find(e.u) ^ Find(e.v)) f[Find(e.u)] = Find(e.v), ans += e.w; return printf("%lld\n", ans), 0;}
- Atcoder CODE FESTIVAL 2017 Final 简要题解
- [DP]Atcoder CODE FESTIVAL 2017 Final (Parallel) D
- Atcoder CODE FESTIVAL 2017 qual C 总结+ABCD题解
- Atcoder CODE FESTIVAL 2017 qual C D
- [Atcoder CODE FESTIVAL 2017 qual C]D
- 【AtCoder CODE FESTIVAL 2017 qual C】D
- 【二分图染色】AtCoder CODE FESTIVAL 2017(qual B)C[3 Steps]题解
- AtCoder Code festival 2017qualC-D-dp+优化
- AtCoder GC 018B: Sports Festival 题解
- Atcoder Code Festival 2016 Qual A D
- [待补完]CODE FESTIVAL 2017 Final (Parallel) A,B,C(搜索)
- atcoder CODE FESTIVAL 2017 qual A 手速(雾)赛
- AGC CODE FESTIVAL 2017 qual A(部分题解)
- [构造] CODE FESTIVAL 2016 Grand Final G. FESTIVAL
- Atcoder Codefestival Exhibition/Team Relay/Tournament Round 简要题解
- CODE FESTIVAL 2017 qual B
- CODE FESTIVAL 2017 qual B
- CODE FESTIVAL 2017 qual A
- webpack 初印象
- kvm基本安装
- android 修改TextView中部分文字的颜色
- Hibernate的学习之路三(映射文件编写)
- laravel 多条件查询用法
- Atcoder CODE FESTIVAL 2017 Final 简要题解
- .git文件夹详解
- WebRTC-命令行参数解析
- Anaconda+eric6+pyqt4步骤(Eric闪退)
- Cortex-M3中断的具体行为
- centos7安装rabbitmq通过tar压缩包方式
- 机器学习算法与Python实践(8)
- iOS 安装证书 打包上线 以及版本更新
- 模式识别 评价方法 ROC曲线, DET曲线, FPPW, FPPI etc.