A. Right-Left Cipher
Solved.
注意长度的奇偶

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 string s; 5 int main() 6 { 7 while (cin >> s) 8 { 9 string res = ""; 10 int len = s.size(); 11 if (len == 1) 12 { 13 cout << s << endl; 14 continue; 15 } 16 int l, r; 17 if (len & 1) 18 { 19 res += s[s.size() / 2]; 20 l = len / 2 - 1, r = l + 2; 21 while (l >= 0) 22 { 23 res += s[r]; 24 res += s[l]; 25 --l, ++r; 26 } 27 } 28 else 29 { 30 l = len / 2 - 1; 31 r = l + 1; 32 while (l >= 0) 33 { 34 res += s[l]; 35 res += s[r]; 36 --l, ++r; 37 } 38 } 39 cout << res << endl; 40 } 41 return 0; 42 }
B. Div Times Mod
Solved.
题意:
$给出一个n,求使得下面这个等式成立的x$
$(frac{x}{k}) cdot (x ;mod; k) = n$
思路:
$k很小,并且第二项的取值肯定在[1, k - 1]之间,枚举第二项,算第一项更新答案即可$

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 int n, k; 6 int main() 7 { 8 while (scanf("%d%d", &n, &k) != EOF) 9 { 10 ll res = (ll)1e18; 11 for (int i = 1; i < k; ++i) if (n % i == 0) 12 res = min(res, 1ll * (n / i) * k + i); 13 printf("%lld ", res); 14 } 15 return 0; 16 }
C. Connect Three
Solved.
题意:
在一个二维平面上,有三个点,在不同的地方,行走只能走相邻的格子且被涂色的格子,求最小的涂格子的数量
思路:
我们随便找两个点,构成的矩形,那么这两个点的路径可以经过这个矩形里面任意一点
那么我们枚举里面每一点,要么第三点也在这个矩形里面,要么肯定存在一点使得这一点到第三点的路径不经过矩形
这样的话答案就会最小
或者这样理解,三点需要汇聚到同一点,那么这个点的候选范围必然是任取两点构成的矩形当中,因为如果不是
那么把这个点移到矩形内必然更优

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int x[3], y[3]; 5 int f(int x1, int y1, int x2, int y2) 6 { 7 return abs(x1 - x2) + abs(y1 - y2); 8 } 9 10 void print(int x1, int y1, int x2, int y2) 11 { 12 while (x2 != x1) 13 { 14 if (x2 < x1) ++x2; 15 else --x2; 16 printf("%d %d ", x2, y2); 17 } 18 while (y2 != y1) 19 { 20 if (y2 < y1) ++y2; 21 else --y2; 22 printf("%d %d ", x2, y2); 23 } 24 } 25 26 int main() 27 { 28 while (scanf("%d%d", x, y) != EOF) 29 { 30 for (int i = 1; i <= 2; ++i) scanf("%d%d", x + i, y + i); 31 int tmp = (int)1e6, posx = -1, posy = -1; 32 int l[2] = {x[0], y[0]}, r[2] = {x[1], y[1]}; 33 for (int i = 0; i < 2; ++i) if (l[i] > r[i]) swap(l[i], r[i]); 34 for (int i = l[0]; i <= r[0]; ++i) for (int j = l[1]; j <= r[1]; ++j) 35 { 36 if (f(i, j, x[2], y[2]) < tmp) 37 { 38 tmp = f(i, j, x[2], y[2]); 39 posx = i, posy = j; 40 } 41 } 42 int res = tmp + f(x[0], y[0], x[1], y[1]) + 1; 43 printf("%d ", res); 44 print(x[0], y[0], posx, posy); 45 print(x[1], y[1], posx, posy); 46 print(x[2], y[2], posx, posy); 47 printf("%d %d ", posx, posy); 48 } 49 return 0; 50 }
D. Minimum Diameter Tree
Solved.
题意:
一棵树,一共有$s的点权,分配给这些点,使得直径最短$
思路:
我们考虑到将点权分配给度数>1的点是没用的,因为它们不会作为路径的端点
那么被作为路径的端点的只有度数=1的点
我们可以这样理解,任意两个度数=1的点都可以构成一条极长路径,也就是说,问题可以转化为
$有x个数,要将s分配给它们,使得两两相加的最大值最小$
$那不就是平均分配吗?$

1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, s, degree[N]; 6 7 int main() 8 { 9 while (scanf("%d%d", &n, &s) != EOF) 10 { 11 memset(degree, 0, sizeof degree); 12 for (int i = 1, u, v; i < n; ++i) 13 { 14 scanf("%d%d", &u, &v); 15 ++degree[u]; 16 ++degree[v]; 17 } 18 int cnt = 0; 19 for (int i = 1; i <= n; ++i) cnt += degree[i] == 1; 20 printf("%.10f ", s * 2.0 / cnt); 21 } 22 return 0; 23 }