Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) Solution
A. Kitchen Utensils
Water.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 110 5 int n, k, cnt[N]; 6 7 int main() 8 { 9 while (scanf("%d%d", &n, &k) != EOF) 10 { 11 memset(cnt, 0, sizeof cnt); 12 for (int i = 1, x; i <= n; ++i) 13 { 14 scanf("%d", &x); 15 ++cnt[x]; 16 } 17 int Max = 0; 18 for (int i = 1; i <= 100; ++i) Max = max(Max, cnt[i] % k == 0 ? cnt[i] / k : cnt[i] / k + 1); 19 int res = 0; 20 for (int i = 1; i <= 100; ++i) if (cnt[i]) 21 { 22 res += Max * k - cnt[i]; 23 } 24 printf("%d\n", res); 25 } 26 return 0; 27 }
B. Personalized Cup
Water.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define INF 0x3f3f3f3f 5 #define N 110 6 int pos[N], w[N], h[N], n; 7 string s; 8 9 void init() 10 { 11 memset(w, 0x3f, sizeof w); 12 memset(h, 0x3f, sizeof h); 13 memset(pos, -1, sizeof pos); 14 for (int i = 100; i >= 1; --i) 15 { 16 for (int j = 1; j <= i; ++j) if (i % j == 0) 17 { 18 int a = i / j, b = j; 19 if (a > b) swap(a, b); 20 if (a <= 5 && b <= 20 && a <= w[i]) 21 { 22 pos[i] = i; 23 w[i] = a; 24 h[i] = b; 25 } 26 if (w[i + 1] < w[i]) 27 { 28 pos[i] = pos[i + 1]; 29 w[i] = w[i + 1]; 30 h[i] = h[i + 1]; 31 } 32 } 33 } 34 } 35 36 int main() 37 { 38 init(); 39 ios::sync_with_stdio(false); 40 cin.tie(0); 41 cout.tie(0); 42 while (cin >> s) 43 { 44 n = s.size(); 45 cout << w[n] << " " << h[n] << "\n"; 46 int need = pos[n] - n; 47 int must = need / w[n]; 48 int remind = need % w[n]; 49 for (int i = 1, pos = 0; i <= w[n]; ++i) 50 { 51 int j = 1; 52 for (; j <= must; ++j) cout << "*"; 53 if (remind) cout << "*", ++j, --remind; 54 for (; j <= h[n]; ++j) cout << s[pos++]; 55 cout << "\n"; 56 } 57 } 58 return 0; 59 }
C. Playing Piano
Upsolved.
思路:每一位枚举,记忆化搜索。$dp[i][j] 表示第i位放j是否可以$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, a[N], res[N], dp[N][10]; 6 7 int DFS(int i, int num) 8 { 9 if (i > n) return 1; 10 int &x = dp[i][num]; 11 if (x != -1) return x; 12 if (a[i] > a[i - 1]) 13 { 14 for (int j = num + 1; j <= 5; ++j) 15 { 16 x = DFS(i + 1, j); 17 if (x) return res[i] = j, x = 1; 18 } 19 } 20 else if (a[i] < a[i - 1]) 21 { 22 for (int j = 1; j < num; ++j) 23 { 24 x = DFS(i + 1, j); 25 if (x) return res[i] = j, x = 1; 26 } 27 } 28 else 29 { 30 for (int j = 1; j <= 5; ++j) if (j != num) 31 { 32 x = DFS(i + 1, j); 33 if (x) return res[i] = j, x = 1; 34 } 35 } 36 return x = 0; 37 } 38 39 int main() 40 { 41 while (scanf("%d", &n) != EOF) 42 { 43 memset(dp, -1, sizeof dp); 44 a[0] = 0; 45 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 46 if (DFS(1, 0)) for (int i = 1; i <= n; ++i) printf("%d%c", res[i], " \n"[i == n]); 47 else puts("-1"); 48 } 49 return 0; 50 }
D. Barcelonian Distance
Solved.
题意:
在一个二维平面中,有一条直线,有两点个点,只能走这条直线上或者方格线上,求两点最短路径
思路:
考虑每个点到直线上通过方格线走只有两种方式,即横着走,纵着走
那么通过直线的方式即有四种
还有一种直接是曼哈顿距离,取$Min$即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 const double eps = 1e-8; 6 ll a, b, c, x[2], y[2]; 7 double xa[2], ya[2], xb[2], yb[2]; 8 9 double dis(double x1, double y1, double x2, double y2) 10 { 11 return sqrt((x1 - x2) * (x1 - x2) * 1.0 + (y1 - y2) * (y1 - y2) * 1.0); 12 } 13 14 double calcx(ll y) 15 { 16 return -(b * y + c) * 1.0 / a; 17 } 18 19 double calcy(ll x) 20 { 21 return -(a * x + c) * 1.0 / b; 22 } 23 24 int main() 25 { 26 while (scanf("%lld%lld%lld", &a, &b, &c) != EOF) 27 { 28 for (int i = 0; i < 2; ++i) scanf("%lld%lld", x + i, y + i); 29 double res = abs(x[0] - x[1]) + abs(y[0] - y[1]); 30 xa[0] = x[0]; ya[0] = calcy(x[0]); 31 xa[1] = calcx(y[0]); ya[1] = y[0]; 32 xb[0] = x[1]; yb[0] = calcy(x[1]); 33 xb[1] = calcx(y[1]); yb[1] = y[1]; 34 for (int i = 0; i < 2; ++i) 35 { 36 for (int j = 0; j < 2; ++j) 37 { 38 res = min(res, dis(x[0], y[0], xa[i], ya[i]) + dis(x[1], y[1], xb[j], yb[j]) + dis(xa[i], ya[i], xb[j], yb[j])); 39 } 40 } 41 printf("%.15f\n", res); 42 } 43 return 0; 44 }
E. The Unbearable Lightness of Weights
Upsolved.
题意:
有n个砝码,知道所有砝码的重量,但是不知道每个砝码和重量的对应关系,可以有一次询问,问用k个砝码组成总重量为m的方案,求最后你最多知道多少个砝码的具体重量
思路:
如果不同重量的砝码种类不超过2,直接输出n
01背包求出拼成重量为w, 物品个数为k的方案数,然后对于每种重量的砝码枚举个数,当且仅当当前个数和数量只有唯一一种方式组成时,那么这个数量就是合法的,可以用来更新答案
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 110 5 int n, sum, tot, a[N], dp[N * N][N], cnt[N], C[N][N]; 6 7 void init() 8 { 9 for (int i = 0; i <= 100; ++i) for (int j = 0; j <= i; ++j) 10 { 11 if (j == 0 || j == i) C[i][j] = 1; 12 else C[i][j] = C[i - 1][j - 1] + C[i - 1][j]; 13 } 14 } 15 16 void Run() 17 { 18 init(); 19 while (scanf("%d", &n) != EOF) 20 { 21 for (int i = 1; i <= n; ++i) 22 { 23 scanf("%d", a + i), sum += a[i], ++cnt[a[i]]; 24 if (cnt[a[i]] == 1) ++tot; 25 } 26 if (tot <= 2) 27 { 28 printf("%d\n", n); 29 continue; 30 } 31 dp[0][0] = 1; 32 for (int i = 1; i <= n; ++i) 33 { 34 for (int j = sum; j >= a[i]; --j) for (int k = 1; k <= n; ++k) 35 dp[j][k] += dp[j - a[i]][k - 1]; 36 } 37 int res = 0; 38 for (int i = 1; i <= 100; ++i) if (cnt[i]) 39 { 40 for (int j = 1; j <= cnt[i]; ++j) 41 { 42 if (dp[i * j][j] == C[cnt[i]][j]) 43 res = max(res, j); 44 } 45 } 46 printf("%d\n", res); 47 } 48 } 49 50 int main() 51 { 52 #ifdef LOCAL 53 freopen("Test.in", "r", stdin); 54 #endif 55 56 Run(); 57 return 0; 58 }
F. Vasya and Maximum Matching
Unsolved.
G. Chattering
Unsolved.