2020牛客暑期多校训练营(第一场)
2020牛客暑期多校训练营(第一场)
比赛地址:
补题开始了,一题题慢慢补吧,顺序由简到难,尽量将能补的题都补了,这篇长久更新。
F Infinite String Comparision
题目地址:
基本思路:
这题很明显不会比较很多次,所以我们我们可以猜一下结论,我们直接尝试将字符串循环比较 次就行了。
参考代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; #define IO std::ios::sync_with_stdio(false) #define int long long #define rep(i, l, r) for (int i = l; i <= r; i++) #define per(i, l, r) for (int i = l; i >= r; i--) #define mset(s, _) memset(s, _, sizeof(s)) #define pb push_back #define pii pair <int, int> #define mp(a, b) make_pair(a, b) #define INF (int)1e18 inline int read() { int x = 0, neg = 1; char op = getchar(); while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); } while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); } return neg * x; } inline void print(int x) { if (x < 0) { putchar('-'); x = -x; } if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } string s1,s2; int solve(){ int k1 = s1.size(),k2 = s2.size(); int p1 = 0,p2 = 0; for(int i = 0 ; i < k1 + k2 + 1; i++){ if(s1[p1] > s2[p2]) return 1; else if(s1[p1] < s2[p2]) return -1; p1 = (p1 + 1) % k1,p2 = (p2 + 1) % k2; } return 0; } signed main() { IO; while (cin >> s1 >> s2){ int tmp = solve(); if(tmp == 1) cout << '>' << '\n'; else if(tmp == -1) cout << '<' << '\n'; else cout << '=' << '\n'; } return 0; }
J Easy Integration
题目地址:
基本思路:
这题正常做法应该是求个积分,但我数学不太好,不太愿算了,提供一下比赛时的非常规做法网络赛现状 。
我们可以用一些计算软件或者高级计算器,算出前几项的结果,然后我们去就能找到公式
预处理一下阶乘求个逆元就能计算答案了。
参考代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; #define IO std::ios::sync_with_stdio(false) #define int long long #define rep(i, l, r) for (int i = l; i <= r; i++) #define per(i, l, r) for (int i = l; i >= r; i--) #define mset(s, _) memset(s, _, sizeof(s)) #define pb push_back #define pii pair <int, int> #define mp(a, b) make_pair(a, b) #define INF (int)1e18 inline int read() { int x = 0, neg = 1; char op = getchar(); while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); } while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); } return neg * x; } inline void print(int x) { if (x < 0) { putchar('-'); x = -x; } if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } const int mod = 998244353; int qpow(int a, int b) { int res = 1; while (b > 0) { if (b & 1) res = 1ll * res * a % mod; a = 1ll * a * a % mod; b >>= 1; } return res; } const int maxn = 2000020; int n,fac[maxn]; signed main() { IO; fac[1] = 1; for (int i = 2; i <= 2000010; i++) fac[i] = fac[i - 1] * i % mod; while (cin >> n) { int t1 = fac[2 * n + 1] % mod; int t2 = fac[n] % mod * fac[n] % mod; int p = t1 * qpow(t2,mod - 2) % mod; int ans = 1ll * qpow(p,mod - 2); cout << ans << '\n'; } return 0; }
I 1 or 2
题目地址:
基本思路:
比较容易看出应该是个网络流匹配,但是难点在于如何构图。
我们将每个点按度拆点,同时再将边拆成两个点,将边对应的点与这个点拆出的每个度点相连,具体构图参照如下:
例如样例的第三个输入度分别为边为,那么构图如下:
那么构图之后我们再求最大匹配(完美匹配一定是最大匹配),如果最大匹配是完美匹配,就证明每条边的两头都匹配了一个点的一个度,并且没有未匹配到的度,那么就是符合要求的。
然后就是带花树求一般图的最大匹配的模板就是了。
参考代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; #define IO std::ios::sync_with_stdio(false) #define int long long #define rep(i, l, r) for (int i = l; i <= r; i++) #define per(i, l, r) for (int i = l; i >= r; i--) #define mset(s, _) memset(s, _, sizeof(s)) #define pb push_back #define pii pair <int, int> #define mp(a, b) make_pair(a, b) #define INF (int)1e18 inline int read() { int x = 0, neg = 1; char op = getchar(); while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); } while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); } return neg * x; } inline void print(int x) { if (x < 0) { putchar('-'); x = -x; } if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } struct edge { int u, v; }e[2005]; int n,m; /****************带花树求一般图最大匹配算法*****************/ int match[1005],newbase; int inqueue[1005],inpath[1005],G[1005][1005],inblossom[1005],father[1005]; int du[1005],c[500005],base[1005],start,finish,head,tail; int lca(int u,int v) { memset(inpath, 0, sizeof inpath); while (true) { u = base[u]; inpath[u] = 1; if (!match[u]) break; u = father[match[u]]; } while (true) { v = base[v]; if (inpath[v]) break; v = father[match[v]]; } return v; } void reset(int u) { while (u != newbase) { int v = match[u]; inblossom[base[v]] = inblossom[base[u]] = 1; u = father[v]; if (base[u] != newbase) father[u] = v; } } void blossomcontract(int u,int v) { newbase = lca(u, v); memset(inblossom, 0, sizeof inblossom); reset(u); reset(v); if (base[u] != newbase) father[u] = v; if (base[v] != newbase) father[v] = u; for (int i = 1; i <= n; i++) if (inblossom[base[i]]) { base[i] = newbase; if (!inqueue[i]) c[++tail] = i, inqueue[i] = 1; } } void findaugmentingpath() { memset(inqueue, 0, sizeof inqueue); memset(father, 0, sizeof father); for (int i = 1; i <= n; i++) base[i] = i; head = 1; tail = 1; c[1] = start; inqueue[start] = 1; finish = 0; while (head <= tail) { int u = c[head++]; for (int v = 1; v <= n; v++) if (G[u][v] && base[u] != base[v] && match[v] != u) { if (v == start || (match[v] > 0) && (father[match[v]] > 0)) { blossomcontract(u, v); } else if (father[v] == 0) { father[v] = u; if (match[v]) { c[++tail] = match[v]; inqueue[match[v]] = 1; } else { finish = v; return; } } } } } void augmentpath() { int u, v, w; u = finish; while (u > 0) { v = father[u]; w = match[v]; match[u] = v; match[v] = u; u = w; } } bool solve() { int res = 0; memset(match, 0, sizeof match); for (int i = 1; i <= n; i++) if (!match[i]) { start = i; findaugmentingpath(); if (finish) augmentpath(), res++; } for (int i = 1; i <= n; i++) if (!match[i]) return false; return true; } /***********************************************************/ vector<int> memo[110]; void build() { // 建图; int cnt = 0; memset(G, 0, sizeof G); for(int i = 0 ; i <= n ; i++) memo[i].clear(); rep(i, 1, n) { rep(j, 1, du[i]) memo[i].push_back(++cnt); } rep(i, 1, m) { int t1 = ++cnt; for (auto it : memo[e[i].u]) G[t1][it] = G[it][t1] = 1; int t2 = ++cnt; for (auto it : memo[e[i].v]) G[t2][it] = G[it][t2] = 1; G[t1][t2] = G[t2][t1] = 1; } n = cnt; } signed main() { while (cin >> n >> m) { for (int i = 1; i <= n; i++) du[i] = read(); for (int i = 1; i <= m; i++) { e[i].u = read(); e[i].v = read(); } build(); if (solve()) { puts("Yes"); } else { puts("No"); } } return 0; }
H Minimum-cost Flow
题目地址:
基本思路:
最近比赛有点多,可能要鸽久一点,咕咕咕(拖延症)