Atcoder ABC390个人游记(A~D)
作者今天很无语,被dmy恶心后状态不好,以为atc会简单,结果又被恶心了,脑子抽了,写的不如以前详细,但是我还是不会改的(
A. 12435
题面
给你一个整数序列 A = ( A 1 , A 2 , A 3 , A 4 , A 5 ) A=(A_1,A_2,A_3,A_4,A_5) A = ( A 1 , A 2 , A 3 , A 4 , A 5 ) ,它是通过对 ( 1 , 2 , 3 , 4 , 5 ) (1,2,3,4,5) ( 1 , 2 , 3 , 4 , 5 ) 进行置换得到的。
请判断 A A A 是否可以通过对 A A A 中相邻的两个元素进行1次 的交换操作来按升序排序。
思路
把正确的数组弄出来,比较差异就行了,很简单。
有没看到相邻结果挂1发的乐子吗
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;int main () { int a[5 ]; cin >> a[0 ] >> a[1 ] >> a[2 ] >> a[3 ] >> a[4 ]; int b[5 ]={a[0 ], a[1 ], a[2 ], a[3 ], a[4 ]}; sort (b, b + 5 ); int pos = 0 ; for (int i = 0 ; i < 5 ; i++) { if (a[i] != b[i]) { pos = i; break ; } } swap (a[pos], a[pos + 1 ]); for (int i = 0 ; i < 5 ; i++) { if (a[i] != b[i]) { cout << "No" ; return 0 ; } } cout << "Yes" ; return 0 ; }
B.Geometric Sequence
题面
问题陈述
给你一个长度为 N N N 的正整数序列 A = ( A 1 , A 2 , … , A N ) A=(A_1,A_2,\ldots,A_N) A = ( A 1 , A 2 , … , A N ) 。
请判断 A A A 是否为几何级数。
思路
很多人因为deepl翻译成几何级数就喷它,你们都是乐子。
百度百科 自己访问。
还有开double的被卡的,hack数据一个循环小数就找出来了。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <bits/stdc++.h> using namespace std;int main () { int n; cin >> n; n -= 2 ; int a, b; cin >> a >> b; int tp = __gcd (a, b); a /= tp; b /= tp; pair<int , int > pii = {a, b}; b *= tp; while (n--) { int c; cin >> c; tp = __gcd (b, c); b /= tp; c /= tp; if (make_pair (b, c) != pii) { cout << "No" ; return 0 ; } c *= tp; b = c; } cout << "Yes" ; return 0 ; }
C.Paint to make a rectangle
题面
给你一个行数为 H H H 列数为 W W W 的网格。
让 ( i , j ) (i,j) ( i , j ) 表示从顶部起位于第 i i i ( 1 ≤ i ≤ H 1 \leq i \leq H 1 ≤ i ≤ H ) 行和从左侧起位于第 j j j ( 1 ≤ j ≤ W 1 \leq j \leq W 1 ≤ j ≤ W ) 列的单元格。
网格的状态由长度为 W W W 的 H H H 字符串 S 1 , S 2 , … , S H S_1, S_2, \ldots, S_H S 1 , S 2 , … , S H 表示,如下所示:
如果 S i S_i S i 的 j j j -th 字符是 “#”,则单元格 ( i , j ) (i,j) ( i , j ) 被涂成黑色。
如果 S i S_i S i 的 j j j -th 字符是 .
,则单元格 ( i , j ) (i,j) ( i , j ) 被涂成白色。
如果 S i S_i S i 的 j j j -th 字符是 ?
,则单元格 ( i , j ) (i,j) ( i , j ) 尚未涂黑。
高桥希望将每个尚未涂色的单元格涂成白色或黑色,这样所有的黑色单元格就组成了一个矩形。
更确切地说,他希望存在一个四元整数 ( a , b , c , d ) (a,b,c,d) ( a , b , c , d ) ( 1 ≤ a ≤ b ≤ H 1 \leq a \leq b \leq H 1 ≤ a ≤ b ≤ H , 1 ≤ c ≤ d ≤ W 1 \leq c \leq d \leq W 1 ≤ c ≤ d ≤ W ),使得:
对于每个单元格 ( i , j ) (i,j) ( i , j ) ( 1 ≤ i ≤ H , 1 ≤ j ≤ W 1 \leq i \leq H, 1 \leq j \leq W 1 ≤ i ≤ H , 1 ≤ j ≤ W ),如果有 a ≤ i ≤ b a \leq i \leq b a ≤ i ≤ b 和 c ≤ j ≤ d c \leq j \leq d c ≤ j ≤ d 则该单元格为黑色;
否则,单元格为白色。
确定这是否可能。
思路
这题让你把所有的黑色格子都要用上,把边界上的找到,再遍历一遍整个数组就好了。
还是很水。C题要想一想,为了防止乐子看不懂,我善意的写好了变量名。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <bits/stdc++.h> using namespace std;int main () { int h, w; cin >> h >> w; vector<string> grid (h) ; for (int i = 0 ; i < h; i++) { cin >> grid[i]; } int row_min = h, row_max = -1 ; int col_min = w, col_max = -1 ; for (int r = 0 ; r < h; r++) { for (int c = 0 ; c < w; c++) { if (grid[r][c] == '#' ) { row_min = min (row_min, r); row_max = max (row_max, r); col_min = min (col_min, c); col_max = max (col_max, c); } } } for (int r = row_min; r <= row_max; r++) { for (int c = col_min; c <= col_max; c++) { if (grid[r][c] == '.' ) { cout << "No" ; return 0 ; } } } cout << "Yes" ; return 0 ; }
D.Stone XOR
题面
有 N N N 个袋子,分别标有袋子 1 1 1 、袋子 2 2 2 、 … \ldots … 、袋子 N N N 。
袋子 i i i ( 1 ≤ i ≤ N 1 \leq i \leq N 1 ≤ i ≤ N )装有 A i A_i A i 块石头。
高桥可以进行以下任意次数的运算,有可能是零:
选择两个袋子 A 和 B,将 A 袋中的所有 棋子移入 B 袋。
在重复操作后,求以下可能出现的不同数值的个数。
B 1 ⊕ B 2 ⊕ ⋯ ⊕ B N B_1 \oplus B_2 \oplus \cdots \oplus B_N B 1 ⊕ B 2 ⊕ ⋯ ⊕ B N ,其中 B i B_i B i 是袋子 i i i 中石头的最终数量。
这里, ⊕ \oplus ⊕ 表示位向 XOR。
关于位向 XOR 对于非负整数 a a a 和 b b b ,位向 XOR a ⊕ b a \oplus b a ⊕ b 的定义如下:
在 a ⊕ b a \oplus b a ⊕ b 的二进制表示中,当且仅当 a a a 和 b b b 的 2 k 2^k 2 k 位上的数字中正好有一位是 1 1 1 时, 2 k 2^k 2 k 位( k ≥ 0 k \ge 0 k ≥ 0 )上的数字是 1 1 1 ;否则,它是 0 0 0 。
例如, 3 ⊕ 5 = 6 3 \oplus 5 = 6 3 ⊕ 5 = 6 (二进制为 011 ⊕ 101 = 110 011 \oplus 101 = 110 0 1 1 ⊕ 1 0 1 = 1 1 0 )。
一般来说,对于 k k k 非负整数 x 1 , x 2 , … , x k x_1, x_2, \ldots, x_k x 1 , x 2 , … , x k ,它们的比特 XOR x 1 ⊕ x 2 ⊕ ⋯ ⊕ x k x_1 \oplus x_2 \oplus \cdots \oplus x_k x 1 ⊕ x 2 ⊕ ⋯ ⊕ x k 被定义为 ( ⋯ ( ( x 1 ⊕ x 2 ) ⊕ x 3 ) ⊕ ⋯ ) ⊕ x k (\cdots((x_1 \oplus x_2) \oplus x_3) \oplus \cdots) \oplus x_k ( ⋯ ( ( x 1 ⊕ x 2 ) ⊕ x 3 ) ⊕ ⋯ ) ⊕ x k ,这与 x 1 , x 2 , … , x k x_1, x_2, \ldots, x_k x 1 , x 2 , … , x k 的阶数无关。
可以证明,在这个问题的约束条件下,可能的值是有限的。
2 ≤ N ≤ 12 2 \leq N \leq 12 2 ≤ N ≤ 1 2
1 ≤ A i ≤ 1 0 17 1 \leq A_i \leq 10^{17} 1 ≤ A i ≤ 1 0 1 7
所有输入值均为整数。
思路
不是,不是,你们看到X O R XOR X O R 就以为它是数学的吗?
不是,不是,你们看到1 0 17 10^{17} 1 0 1 7 还想着D P DP D P ?
不是,不是,你们没看到时限3 3 3 秒吗?
子集枚举就ok了,你可以再用状压,也可以再用h a s h hash h a s h 表,不理解为什么那么多人没过。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 #include <bits/stdc++.h> using namespace std;typedef long long ll;int main () { ios::sync_with_stdio (false ); cin.tie (0 ); int n; cin >> n; vector<ll> a (n) ; for (auto &x : a) cin >> x; vector<ll> c (n, 0 ) ; for (int i = 0 ; i < n; i++) c[i] = min (a[i], (ll)(n - i - 1 )); int max_iters = 10 ; while (max_iters--) { vector<ll> add (n + 2 , 0LL ) ; for (int j = 0 ; j < n; j++) { if (c[j] == 0 ) continue ; ll l = j + 1 ; ll r = j + c[j]; if (l >= n) continue ; r = min (r, (ll)(n - 1 )); add[l] += 1 ; if (r + 1 < n) add[r + 1 ] -= 1 ; } vector<ll> received (n, 0 ) ; received[0 ] = add[0 ]; for (int i = 1 ; i < n; i++) received[i] = received[i - 1 ] + add[i]; bool changed = false ; for (int i = 0 ; i < n; i++) { ll new_c = min (a[i] + received[i], (ll)(n - i - 1 )); if (new_c != c[i]) { c[i] = new_c; changed = true ; } } if (!changed) break ; } vector<ll> add_final (n + 2 , 0LL ) ; for (int j = 0 ; j < n; j++) { if (c[j] == 0 ) continue ; ll l = j + 1 ; ll r = j + c[j]; if (l >= n) continue ; r = min (r, (ll)(n - 1 )); add_final[l] += 1 ; if (r + 1 < n) add_final[r + 1 ] -= 1 ; } vector<ll> received_final (n, 0 ) ; received_final[0 ] = add_final[0 ]; for (int i = 1 ; i < n; i++) received_final[i] = received_final[i - 1 ] + add_final[i]; vector<ll> final_gems (n, 0 ) ; for (int i = 0 ; i < n; i++) { ll given = c[i]; ll received = received_final[i]; final_gems[i] = a[i] - given + received; } for (int i = 0 ; i < n; i++) { cout << final_gems[i] << ' ' ; } }#include <bits/stdc++.h> using namespace std;#define int long long int a[12 ], n;unordered_set<int > s; void dfs (int idx, int used, int blockSum[12 ]) { if (idx == n) { if (used <= n) { int x = 0 ; for (int i = 0 ; i < used; i++) { x ^= blockSum[i]; } s.insert (x); } return ; } for (int i = 0 ; i < used; i++) { blockSum[i] += a[idx]; dfs (idx + 1 , used, blockSum); blockSum[i] -= a[idx]; } blockSum[used] = a[idx]; dfs (idx + 1 , used + 1 , blockSum); blockSum[used] = 0 ; return ; } signed main () { cin >> n; for (int i = 0 ; i < n; i++) { cin >> a[i]; } int blockSum[12 ]; memset (blockSum, 0 , sizeof (blockSum)); dfs (0 , 0 , blockSum); cout << s.size (); return 0 ; }
E.Vitamin Balance
数组开小了居然TLE,没改出来,痛失。
(我说为什么只有AC和TLE的点而且两个时间差距大的离谱)
总结
总个锤啊,有啥好总结的。
要总结,就是数组开小可能会TLE,但是我还是不知道为啥。