Mail.Ru Cup 2018 Round 3 Solution
A. Determine Line
Water.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int n, vis[110]; 5 6 int main() 7 { 8 while (scanf("%d", &n) != EOF) 9 { 10 memset(vis, 0, sizeof vis); 11 for (int i = 1, tot, x; i <= n; ++i) 12 { 13 scanf("%d", &tot); 14 while (tot--) 15 { 16 scanf("%d", &x); 17 ++vis[x]; 18 } 19 } 20 for (int i = 1; i <= 100; ++i) if (vis[i] == n) printf("%d ", i); 21 puts(""); 22 } 23 return 0; 24 }
B. Divide Candies
Solved.
题意:
有$n \cdot n 的网格,每个网格放的糖数是(i^2 + j^2), i, j 表示行列$
求有多少个格子上的糖数是$m的倍数$
思路:
因为$m很小,处理出m的每个余数所对应的数字个数,再加加乘乘就好了$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 int n, m; 6 ll cnt[1010]; 7 8 ll calc(ll x, ll y) 9 { 10 if (x % m >= y) return x / m + 1; 11 return x / m; 12 } 13 14 int main() 15 { 16 while (scanf("%d%d", &n, &m) != EOF) 17 { 18 memset(cnt, 0, sizeof cnt); 19 for (int i = 0; i < m; ++i) 20 cnt[i * i % m] += calc(n, i); 21 --cnt[0]; cnt[m] = cnt[0]; 22 ll res = 0; 23 for (int i = 0; i < m; ++i) res += cnt[i] * cnt[m - i]; 24 printf("%lld\n", res); 25 } 26 return 0; 27 }
C. Pick Heroes
Solved.
题意:
有两支队伍,每支队伍$n个人,每个人要选一个英雄,一共有2 \cdot n 个英雄$
$两支队伍的人轮流选,但是有些英雄有对应关系,也就是说如果某一轮一个人选了其中一个$
$那么在下一轮他的对手将被强制选择另一个,每个英雄最多存在于一个对应关系中$
这里是交互题。
思路:
贪心选即可,注意自己先手的时候,尽量先贪心选有对应关系的大的那只,再从大往小取
后手的时候注意特判,自己可不可以选有对应关系的英雄,如果可以,那么就回到先手状态
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 2010 5 #define pii pair <int, int> 6 int n, m, t; 7 vector <pii> v, p; 8 map <int, int> mp; 9 int vis[N]; 10 11 int main() 12 { 13 while (scanf("%d%d", &n, &m) != EOF) 14 { 15 v.clear(); mp.clear(); p.clear(); 16 memset(vis, 0, sizeof vis); 17 for (int i = 1, x; i <= 2 * n; ++i) 18 { 19 scanf("%d", &x); 20 p.emplace_back(x, i); 21 } 22 for (int i = 1, x, y; i <= m; ++i) 23 { 24 scanf("%d%d", &x, &y); 25 mp[x] = y; 26 mp[y] = x; 27 v.emplace_back(x, y); 28 } 29 scanf("%d", &t); 30 for (auto &it : v) if (p[it.first - 1].first < p[it.second - 1].first) swap(it.first, it.second); 31 sort(p.begin(), p.end(), [](pii a, pii b) { return a.first > b.first; }); 32 if (t == 1) 33 { 34 int x; 35 for (auto &it : v) 36 { 37 printf("%d\n", it.first); 38 fflush(stdout); 39 scanf("%d", &x); 40 vis[it.first] = 1; 41 vis[x] = 1; 42 } 43 for (int i = v.size() + 1, r = 0; i <= n; ++i) 44 { 45 while (vis[p[r].second]) ++r; 46 printf("%d\n", p[r].second); 47 fflush(stdout); 48 scanf("%d", &x); 49 vis[p[r].second] = 1; 50 vis[x] = 1; 51 } 52 } 53 else 54 { 55 int x; 56 for (int i = 1, r1 = 0, r2 = 0; i <= n; ++i) 57 { 58 scanf("%d", &x); 59 vis[x] = 1; 60 if (mp.find(x) != mp.end() && vis[mp[x]] == 0) 61 { 62 printf("%d\n", mp[x]); 63 vis[mp[x]] = 1; 64 } 65 else 66 { 67 while (r1 < v.size() && vis[v[r1].first]) ++r1; 68 if (r1 < v.size()) 69 { 70 printf("%d\n", v[r1].first); 71 vis[v[r1].first] = 1; 72 } 73 else 74 { 75 while (vis[p[r2].second]) ++r2; 76 printf("%d\n", p[r2].second); 77 vis[p[r2].second] = 1; 78 } 79 } 80 fflush(stdout); 81 } 82 } 83 84 } 85 return 0; 86 }
D. Decorate Apple Tree
Solved.
题意:
有一棵树,每个叶子要有一个颜色。
一个点被定义为好点,是在它的子树中每个叶子的颜色都不同。
求好点个数为$k的时候 k \in [1, n] 所需要的最小的颜色个数$
思路:
先处理出每个点的子树中有多少个叶子,再按从小到大排序,依次输出即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n; 6 vector <int> G[N]; 7 8 int sze[N]; 9 void DFS(int u) 10 { 11 sze[u] = 0; 12 for (auto v : G[u]) 13 { 14 DFS(v); 15 sze[u] += sze[v]; 16 } 17 if (!sze[u]) sze[u] = 1; 18 } 19 20 int main() 21 { 22 while (scanf("%d", &n) != EOF) 23 { 24 for (int i = 1; i <= n; ++i) G[i].clear(); 25 for (int u = 2, v; u <= n; ++u) 26 { 27 scanf("%d", &v); 28 G[v].push_back(u); 29 } DFS(1); 30 sort(sze + 1, sze + 1 + n); 31 for (int i = 1; i <= n; ++i) printf("%d%c", sze[i], " \n"[i == n]); 32 } 33 return 0; 34 }
E. Check Transcription
Unsolved.
题意:
给出一个01串,以及一个字符串,求找出两个小串$A, B$
$使得01串为0的位置填A, 为1的位置填B,最后组成的串为给出的字符串$
求存在多少个$pairs(A, B)$
F. Write The Contest
Unsolved.
G. Take Metro
Unsolved.
H. Detect Robots
Unsolved.