2018 Multi-University Training Contest 1 Solution
A - Maximum Multiple
题意:给出一个n 找x, y, z 使得$n = x + y +z$ 并且 $n \equiv 0 \pmod x, n \equiv 0 \pmod y, n \equiv 0 \pmod z$ 并且使得 $x \cdot y \cdot z$ 最大
思路:设$a = \frac{n}{x}, b = \frac{n}{y}, c = \frac{n}{z}$ 那么 $\frac{1}{a} + \frac{1}{b} + \frac{1}{c} = 1$ 那么我们考虑去凑 a, b, c
两种方案 ${3, 3, 3}$ 或者 ${2, 4, 4}$ 取max
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 ll n; 8 9 int main() 10 { 11 int t; 12 scanf("%d", &t); 13 while(t--) 14 { 15 scanf("%lld", &n); 16 if(n % 3 == 0) 17 { 18 ll ans = n / 3; 19 ans *= n / 3; 20 ans *= n / 3; 21 printf("%lld\n", ans); 22 } 23 else if(n % 4 == 0) 24 { 25 ll ans = n / 2; 26 ans *= n / 4; 27 ans *= n / 4; 28 printf("%lld\n", ans); 29 } 30 else 31 { 32 puts("-1"); 33 } 34 } 35 return 0; 36 }
B - Balanced Sequence
题意:求如何拼接 使得balanced Sequence 最长
思路:首先预处理,使得剩下的串都是 ((( 或者 ))) 或者 )))(((
((( 这种都放左边 ))) 都放右边 目前的问题就是 )))((( 这种在中间按什么顺序放使得答案最大
我们定义 $L_1, R_1$ $L_2, R_2$ 分别为两个串的左括号数量和右括号数量
假如 1 放在 2前面 那么对答案的贡献是 $min(R_1, L_2)$
假如 1 放在 2 后面 那么对答案的贡献是 $min(R_2, L_1)$
比较对答案的贡献,哪个答案贡献大,选哪种放置方式
如果读答案的贡献一样大,那么我们让左括号多的放前面 因为这样对后面的答案贡献大
Dup4:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define N 100010 6 7 struct node 8 { 9 int l, r; 10 inline node() {} 11 inline node(int l, int r) : l(l), r(r) {} 12 inline bool operator < (const node &b) const 13 { 14 int t1 = min(l, b.r), t2 = min(r, b.l); 15 return t1 > t2 || (t1 == t2 && (l > b.l)); 16 } 17 }arr[N]; 18 19 int t, n; 20 char s[N]; 21 22 int main() 23 { 24 scanf("%d", &t); 25 while (t--) 26 { 27 int L = 0, R = 0, ans = 0, cnt = 0; 28 scanf("%d", &n); 29 for (int i = 1; i <= n; ++i) 30 { 31 scanf("%s", s); 32 int LL = 0, RR = 0; 33 for (int j = 0, len = strlen(s); j < len; ++j) 34 { 35 if (s[j] == '(') 36 ++LL; 37 else 38 { 39 if (LL) 40 { 41 --LL; 42 ans += 2; 43 } 44 else 45 ++RR; 46 } 47 } 48 if (LL && RR) 49 arr[++cnt] = node(LL, RR); 50 else if (LL) L += LL; 51 else R += RR; 52 } 53 sort(arr + 1, arr + 1 + cnt); 54 for (int i = 1; i <= cnt; ++i) 55 { 56 int LL = arr[i].l, RR = arr[i].r; 57 ans += min(L, RR) * 2; 58 L -= min(L, RR); 59 L += LL; 60 } 61 ans += min(L, R) * 2; 62 printf("%d\n", ans); 63 } 64 return 0; 65 }
XHT:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define N 100010 6 7 struct node 8 { 9 int l, r; 10 inline node() {} 11 inline node(int l, int r) : l(l), r(r) {} 12 inline bool operator < (const node &b) const 13 { 14 if(l >= r && b.l < b.r) 15 return true; 16 if(l < r && b.l >= b.r) 17 return false; 18 if(l >= r && b.l >= b.r) 19 return r < b.r; 20 if(l < r && b.l < b.r) 21 return l > b.l; 22 } 23 }arr[N]; 24 25 int t, n; 26 char s[N]; 27 28 int main() 29 { 30 scanf("%d", &t); 31 while (t--) 32 { 33 int ans = 0; 34 scanf("%d", &n); 35 for (int i = 1; i <= n; ++i) 36 { 37 scanf("%s", s); 38 int LL = 0, RR = 0; 39 for (int j = 0, len = strlen(s); j < len; ++j) 40 { 41 if (s[j] == '(') 42 ++LL; 43 else 44 { 45 if (LL) 46 { 47 --LL; 48 ans += 2; 49 } 50 else 51 ++RR; 52 } 53 } 54 arr[i] = node(LL, RR); 55 } 56 sort(arr + 1, arr + 1 + n); 57 int L = 0; 58 for (int i = 1; i <= n; ++i) 59 { 60 int LL = arr[i].l, RR = arr[i].r; 61 ans += min(L, RR) * 2; 62 L -= min(L, RR); 63 L += LL; 64 } 65 printf("%d\n", ans); 66 } 67 return 0; 68 }
C - Triangle Partition
水.(排序)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e3 + 10; 6 7 struct node{ 8 int x, y, id; 9 inline node(){} 10 inline node(int x, int y, int id):x(x), y(y), id(id){} 11 inline bool operator < (const node &b) const 12 { 13 return x == b.x ? y < b.y : x < b.x; 14 } 15 }P[maxn << 2]; 16 17 int n; 18 19 int main() 20 { 21 int t; 22 scanf("%d", &t); 23 while(t--) 24 { 25 scanf("%d", &n); 26 for(int i = 1; i <= 3 * n; ++i) 27 { 28 scanf("%d %d", &P[i].x, &P[i].y); 29 P[i].id = i; 30 } 31 sort(P + 1, P + 1 + 3 * n); 32 for(int i = 1; i <= 3 * n; i += 3) 33 { 34 printf("%d %d %d\n", P[i].id, P[i + 1].id, P[i + 2].id); 35 } 36 } 37 return 0; 38 }
D - Distinct Values
按题意模拟即可。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define N 100010 6 7 struct node 8 { 9 int l, r; 10 inline void scan() 11 { 12 scanf("%d%d", &l, &r); 13 } 14 inline bool operator < (const node &r) const 15 { 16 return l < r.l || (l == r.l && this->r > r.r); 17 } 18 }Data[N]; 19 20 int t, n, m; 21 int ans[N]; 22 bool vis[N]; 23 int R; 24 25 int main() 26 { 27 scanf("%d", &t); 28 while (t--) 29 { 30 memset(ans, 0, sizeof ans); 31 R = 0; 32 scanf("%d%d", &n, &m); 33 for (int i = 1; i <= m; ++i) Data[i].scan(); 34 sort(Data + 1, Data + 1 + m); 35 for (int i = 1; i <= m; ++i) 36 { 37 int l = Data[i].l, r = Data[i].r; 38 if (R >= r) continue; 39 if (R + 1 < l) 40 for (int j = R + 1; j < l; ++j) ans[j] = 1; 41 memset(vis, false, sizeof vis); 42 for (int j = l; j <= R; ++j) vis[ans[j]] = true; 43 int L = 1; 44 for (int j = max(R + 1, l); j <= r; ++j) 45 { 46 while (vis[L]) ++L; 47 ans[j] = L; 48 vis[L] = true; 49 } 50 R = max(R, r); 51 } 52 while (R < n) 53 { 54 R++; 55 ans[R] = 1; 56 } 57 for (int i = 1; i <= n; ++i) printf("%d%c", ans[i], " \n"[i == n]); 58 } 59 return 0; 60 }
E - Maximum Weighted Matching
留坑。
F - Period Sequence
留坑。
G - Chiaki Sequence Revisited
题意:定义$a_n$ 求 $\sum_{i = 1} ^ {i = n} a_i$
思路:先不考虑$a_1$
我们对每个最后一个2的幂次数处理出它前面有多少个数, 以及这些数的前缀和是多少
比如说处理出
1 2 4 8 16
1 3 7 15 31
1 5 20 76 288
然后给出n计算的时候 按二进制拆分 比如说
27 = 15 + 7 + 3 + 3
定义$F[i] 为 前面i个数的前缀和$
$ans[27] = F[15] + F[7] + 7 * 8 + F[3] + 3 * (8 + 2) + F[3] + 3 * (8 + 2 + 2)$
对于后面,相当于所有数向右偏移
注意取模
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define N 64 6 #define ll long long 7 8 const ll MOD = (ll)1e9 + 7; 9 10 int t; 11 ll n; 12 ll a[N], b[N], c[N]; 13 14 inline void Init() 15 { 16 a[0] = 1; 17 for (int i = 1; i <= 59; ++i) a[i] = a[i - 1] << 1; 18 b[0] = 1; 19 for (int i = 1; i <= 59; ++i) b[i] = (b[i - 1] << 1) + 1; 20 c[0] = 1; 21 for (int i = 1; i <= 59; ++i) c[i] = ((c[i - 1] << 1) % MOD + (a[i - 1] % MOD) * (b[i - 1] % MOD) % MOD + a[i]) %MOD; 22 // for (int i = 0; i <= 59; ++i) printf("%lld %lld %lld\n", a[i], b[i], c[i]); 23 } 24 25 int main() 26 { 27 Init(); scanf("%d", &t); 28 while (t--) 29 { 30 scanf("%lld", &n); --n; 31 ll ans = 1, tmp = 0; 32 for (int i = 59; i >= 0; --i) 33 { 34 while (n >= b[i]) 35 { 36 ans = (ans + c[i]) % MOD; 37 ans = (ans + (b[i] % MOD * tmp) % MOD) % MOD; 38 tmp = (tmp + a[i]) % MOD; 39 n -= b[i]; 40 } 41 } 42 printf("%lld\n", ans); 43 } 44 return 0; 45 }
H - RMQ Similar Sequence
留坑。
I - Lyndon Substring
留坑。
J - Turn Off The Light
留坑。
K - Time Zone
按题意模拟即可
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 int t, a, b; 6 char s[10]; 7 8 inline void work1() 9 { 10 int ans = 0; int flag = 1; 11 if (s[0] == '-') 12 flag = -1; 13 int len = strlen(s); 14 for (int i = 1; i < len; ++i) 15 ans = ans * 10 + s[i] - '0'; 16 ans *= flag; 17 int gap = ans - 8; 18 a = (a + gap + 24) % 24; 19 printf("%02d:%02d\n", a, b); 20 return; 21 } 22 23 inline void work2() 24 { 25 int A = 0, B = 0; int flag = 1; 26 if (s[0] == '-') 27 flag = -1; 28 int len = strlen(s), i; 29 for (i = 1; s[i] != '.'; ++i) 30 A = A * 10 + s[i] - '0'; 31 for (++i; i < len; ++i) 32 B = B * 10 + s[i] - '0'; 33 int tot = a * 60 + b; 34 A *= flag, B = B * 6 * flag; 35 int tmptot = A * 60 + B - 480; 36 tot = (tot + tmptot + 24 * 60) % (24 * 60); 37 printf("%02d:%02d\n", tot / 60, tot % 60); 38 return; 39 } 40 41 int main() 42 { 43 scanf("%d", &t); 44 while (t--) 45 { 46 scanf("%d %d UTC%s", &a, &b, s); 47 bool flag = true; 48 for (int i = 0, len = strlen(s); i < len; ++i) 49 if (s[i] == '.') 50 { 51 flag = false; 52 break; 53 } 54 if (flag) work1(); 55 else work2(); 56 } 57 return 0; 58 }