A. Increasing and Decreasing
You are given three integers x x x, y y y, and n n n.
Your task is to construct an array a a a consisting of n n n integers which satisfies the following conditions:
- a 1 = x a_1=x a1=x, a n = y a_n=y an=y;
- a a a is strictly increasing (i.e. a 1 < a 2 < … < a n a_1 < a_2 < \ldots < a_n a1<a2<…<an);
- if we denote b i = a i + 1 − a i b_i=a_{i+1}-a_{i} bi=ai+1−ai for 1 ≤ i ≤ n − 1 1 \leq i \leq n-1 1≤i≤n−1, then b b b is strictly decreasing (i.e. b 1 > b 2 > … > b n − 1 b_1 > b_2 > \ldots > b_{n-1} b1>b2>…>bn−1).
If there is no such array a a a, print a single integer − 1 -1 −1.
Input
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1000 1 \le t \le 1000 1≤t≤1000). The description of the test cases follows.
The only line of each test case contains three integers x x x, y y y, n n n ( 1 ≤ x < y ≤ 1000 , 3 ≤ n ≤ 1000 1 \le x < y \le 1000,3 \le n \le 1000 1≤x<y≤1000,3≤n≤1000).
Output
For each test case, output n n n integers a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,…,an. If there are multiple solutions, print any of them.
If there is no solution, print a single integer − 1 -1 −1.
Example
input
3
1 4 3
1 3 3
100 200 4
output
1 3 4
-1
100 150 180 200
Note
In the first test case, a = [ 1 , 3 , 4 ] a=[1,3,4] a=[1,3,4], which is strictly increasing. Next, b 1 = a 2 − a 1 = 3 − 1 = 2 b_1=a_2-a_1=3-1=2 b1=a2−a1=3−1=2, b 2 = a 3 − a 2 = 4 − 3 = 1 b_2=a_3-a_2=4-3=1 b2=a3−a2=4−3=1, thus b = [ 2 , 1 ] b=[2,1] b=[2,1], which is strictly decreasing.
In the second test case, there is no array a a a that satisfies all the conditions above.
Tutorial
利用贪心,对于所有的
i
(
1
<
i
<
n
)
i(1 < i < n)
i(1<i<n),都有
a
i
=
a
i
+
1
−
(
n
−
i
)
a_i = a_{i + 1} - (n - i)
ai=ai+1−(n−i) ,则需要满足
a
2
−
a
1
≥
n
−
1
a_2 - a_1 \ge n - 1
a2−a1≥n−1 才能有解
Solution
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
void solve() {
int x, y, n, diff = 1;
cin >> x >> y >> n;
vector<int> ans;
ans.emplace_back(y);
for (int i = 1; i < n; ++i) {
ans.emplace_back(ans.back() - diff);
diff++;
}
ranges::reverse(ans);
if (ans[0] < x) {
cout << -1 << endl;
return;
}
cout << x << " \n"[n == 1];
for (int i = 1; i < n; ++i) {
cout << ans[i] << " \n"[i == n - 1];
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
int test; cin >> test; while (test--)
solve();
return 0;
}
B. Swap and Reverse
You are given a string s s s of length n n n consisting of lowercase English letters, and an integer k k k. In one step you can perform any one of the two operations below:
- Pick an index i i i ( 1 ≤ i ≤ n − 2 1 \le i \le n - 2 1≤i≤n−2) and swap s i s_{i} si and s i + 2 s_{i+2} si+2.
- Pick an index i i i ( 1 ≤ i ≤ n − k + 1 1 \le i \le n-k+1 1≤i≤n−k+1) and reverse the order of letters formed by the range [ i , i + k − 1 ] [i,i+k-1] [i,i+k−1] of the string. Formally, if the string currently is equal to s 1 … s i − 1 s i s i + 1 … s i + k − 2 s i + k − 1 s i + k … s n − 1 s n s_1\ldots s_{i-1}s_is_{i+1}\ldots s_{i+k-2}s_{i+k-1}s_{i+k}\ldots s_{n-1}s_n s1…si−1sisi+1…si+k−2si+k−1si+k…sn−1sn, change it to s 1 … s i − 1 s i + k − 1 s i + k − 2 … s i + 1 s i s i + k … s n − 1 s n s_1\ldots s_{i-1}s_{i+k-1}s_{i+k-2}\ldots s_{i+1}s_is_{i+k}\ldots s_{n-1}s_n s1…si−1si+k−1si+k−2…si+1sisi+k…sn−1sn.
You can make as many steps as you want (possibly, zero). Your task is to find the lexicographically smallest string you can obtain after some number of steps.
A string a a a is lexicographically smaller than a string b b b of the same length if and only if the following holds:
- in the first position where a a a and b b b differ, the string a a a has a letter that appears earlier in the alphabet than the corresponding letter in b b b.
Input
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104). The description of the test cases follows.
The first line of each test case contains two integers n n n and k k k ( 1 ≤ k < n ≤ 1 0 5 1 \le k < n \le 10^5 1≤k<n≤105).
The second line of each test case contains the string s s s of length n n n consisting of lowercase English letters.
It is guaranteed that the sum of n n n over all test cases does not exceed 1 0 5 10^5 105.
Output
For each test case, print the lexicographically smallest string after doing some (possibly, zero) steps.
Example
input
5
4 2
nima
5 3
panda
9 2
theforces
7 3
amirfar
6 4
rounds
output
aimn
aandp
ceefhorst
aafmirr
dnorsu
Note
In the first test case, we can obtain the string “aimn” using the following operations:
- Reverse the range [ 3 , 4 ] [3,4] [3,4]. The string turns into “niam”.
- Swap s 1 s_1 s1 and s 3 s_3 s3. The string turns into “ainm”.
- Reverse the range [ 3 , 4 ] [3,4] [3,4]. The string turns into “aimn”.
It can be proven that we cannot obtain any string lexicographically smaller than “aimn”. Therefore, “aimn” is the answer.
In the second test case, we can obtain the string “aandp” using the following operations:
- Swap s 3 s_3 s3 and s 5 s_5 s5. The string turns into “paadn”.
- Swap s 1 s_1 s1 and s 3 s_3 s3. The string turns into “aapdn”.
- Swap s 3 s_3 s3 and s 5 s_5 s5. The string turns into “aandp”.
It can be proven that we cannot obtain any string lexicographically smaller than “aandp”. Therefore, “aandp” is the answer.
Tutorial
由题意得,对于每个
i
(
1
≥
i
≥
n
−
2
)
i(1 \ge i \ge n - 2)
i(1≥i≥n−2),都可以交换
s
i
s_i
si 和
s
i
+
2
s_{i + 2}
si+2,这一操作其实可以理解为对于这个字符串
s
s
s,其奇数下标位置之间可以相互交换,偶数下标位置之间也可以相互交换,所以无论
k
k
k 取什么值,奇数位置之间和偶数位置之间都可以相互交换,那么当什么时候可以使奇数下标位置和偶数下标位置之间交换呢?
这个时候就需要对 k k k 进行讨论,如果 k k k 是奇数,那么必定可以存在 s 1 s_1 s1 和 s 1 + k s_{1 + k} s1+k 交换,此时使原本处于奇数下标位置的字符交换到了偶数下标位置,此时说明整个字符串都可以任意排序
综上所述,可以分为以下两种情况讨论:
- k k k 为奇数时,直接对字符串 s s s 进行排序即可,因为此时任意两个字符都可以通过交换到达想要的位置
- k k k 为偶数时,可以在奇数下标位置之间进行排序,偶数下标位置纸巾进行排序
Solution
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define endl '\n'
#define int long long
void solve() {
int n, k;
string s;
cin >> n >> k >> s;
if (k & 1) {
vector<pair<char, int>> a;
for (int i = 0; i < n; ++i) {
a.emplace_back(s[i], i);
}
ranges::sort(a);
string ans = string(" ", n);
int l = 0, r = 1;
for (PII ai : a) {
if (ai.se & 1) {
ans[r] = ai.fi;
r += 2;
} else {
ans[l] = ai.fi;
l += 2;
}
}
cout << ans << endl;
} else {
ranges::sort(s);
cout << s << endl;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
int test; cin >> test; while (test--)
solve();
return 0;
}
C. Divisor Chain
You are given an integer x x x. Your task is to reduce x x x to 1 1 1.
To do that, you can do the following operation:
- select a divisor d d d of x x x, then change x x x to x − d x-d x−d, i.e. reduce x x x by d d d. (We say that d d d is a divisor of x x x if d d d is an positive integer and there exists an integer q q q such that x = d ⋅ q x = d \cdot q x=d⋅q.)
There is an additional constraint: you cannot select the same value of d d d more than twice.
For example, for x = 5 x=5 x=5, the following scheme is invalid because 1 1 1 is selected more than twice: 5 → − 1 4 → − 1 3 → − 1 2 → − 1 1 5\xrightarrow{-1}4\xrightarrow{-1}3\xrightarrow{-1}2\xrightarrow{-1}1 5−14−13−12−11. The following scheme is however a valid one: 5 → − 1 4 → − 2 2 → − 1 1 5\xrightarrow{-1}4\xrightarrow{-2}2\xrightarrow{-1}1 5−14−22−11.
Output any scheme which reduces x x x to 1 1 1 with at most 1000 1000 1000 operations. It can be proved that such a scheme always exists.
Input
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1000 1 \le t \le 1000 1≤t≤1000). The description of the test cases follows.
The only line of each test case contains a single integer x x x ( 2 ≤ x ≤ 1 0 9 2\le x \le 10^{9} 2≤x≤109).
Output
For each test case, output two lines.
The first line should contain an integer k k k ( 1 ≤ k ≤ 1001 1 \le k \le 1001 1≤k≤1001).
The next line should contain k k k integers a 1 , a 2 , … , a k a_1,a_2,\ldots,a_k a1,a2,…,ak, which satisfy the following:
- a 1 = x a_1=x a1=x;
- a k = 1 a_k=1 ak=1;
- for each 2 ≤ i ≤ k 2 \le i \le k 2≤i≤k, the value ( a i − 1 − a i ) (a_{i-1}-a_i) (ai−1−ai) is a divisor of a i − 1 a_{i-1} ai−1. Each number may occur as a divisor at most twice.
Example
input
3
3
5
14
output
3
3 2 1
4
5 4 2 1
6
14 12 6 3 2 1
Note
In the first test case, we use the following scheme: 3 → − 1 2 → − 1 1 3\xrightarrow{-1}2\xrightarrow{-1}1 3−12−11.
In the second test case, we use the following scheme: 5 → − 1 4 → − 2 2 → − 1 1 5\xrightarrow{-1}4\xrightarrow{-2}2\xrightarrow{-1}1 5−14−22−11.
In the third test case, we use the following scheme: 14 → − 2 12 → − 6 6 → − 3 3 → − 1 2 → − 1 1 14\xrightarrow{-2}12\xrightarrow{-6}6\xrightarrow{-3}3\xrightarrow{-1}2\xrightarrow{-1}1 14−212−66−33−12−11.
Tutorial
个人认为本题方法比较巧妙,先将
x
x
x 转换为二进制数,每次将最低位的 1
直接减去即可,因为高位 1
一定可以拆分为多个低位 1
,即满足
x
=
d
⋅
q
x = d \cdot q
x=d⋅q,这样一直拆解到只剩一位 1
拆解到只剩一位 1
后,就很简单处理了,直接每次减去当前数的一半,这样必定不会出现两次连续一样的
d
d
d,最后也必定是以 1
结束
Solution
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define lowbit(x) x & -x
#define sqrt(x) __builtin_sqrt(x)
void solve() {
int x;
cin >> x;
vector<int> ans;
while (popcount(x) > 1) {
ans.emplace_back(x);
x -= lowbit(x);
}
while (x >= 1) {
ans.emplace_back(x);
x >>= 1;
}
int l = ans.size();
cout << l << endl;
for (int i = 0; i < l; ++i) {
cout << ans[i] << " \n"[i == l - 1];
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
int test; cin >> test; while (test--)
solve();
return 0;
}
D. Matrix Cascade
There is a matrix of size n × n n \times n n×n which consists of 0s and 1s. The rows are numbered from 1 1 1 to n n n from top to bottom, the columns are numbered from 1 1 1 to n n n from left to right. The cell at the intersection of the x x x-th row and the y y y-th column is denoted as ( x , y ) (x, y) (x,y).
AquaMoon wants to turn all elements of the matrix to 0s. In one step she can perform the following operation:
- Select an arbitrary cell, let it be ( i , j ) (i, j) (i,j), then invert the element in ( i , j ) (i, j) (i,j) and also invert all elements in cells ( x , y ) (x, y) (x,y) for x > i x > i x>i and x − i ≥ ∣ y − j ∣ x - i \ge \left|y - j\right| x−i≥∣y−j∣. To invert a value means to change it to the opposite: 0 changes to 1, 1 changes to 0.
Help AquaMoon determine the minimum number of steps she need to perform to turn all elements of the matrix to 0s. We can show that an answer always exists.
Input
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1≤t≤105). The description of the test cases follows.
The first line of each test case contains an integer n n n ( 2 ≤ n ≤ 3000 2 \le n \le 3000 2≤n≤3000).
The i i i-th of the following n n n lines contains a binary string only of characters 0 and 1, of length n n n.
It is guaranteed that the sum of n 2 n^2 n2 over all test cases does not exceed 9 000 000 9\,000\,000 9000000.
Output
For each test case, print the minimum number of steps.
Example
input
3
5
00100
01110
11111
11111
11111
3
100
110
110
6
010101
111101
011110
000000
111010
001110
output
1
2
15
Note
In the first test case, we can use the following scheme:
- perform the operation on the cell ( 1 , 3 ) (1, 3) (1,3).
Clearly, the elements of the initial matrix are not all 0, so at least one operation is required. Thus, 1 1 1 is the answer.
In the second test case, we use the following scheme:
- perform the operation on the cell ( 3 , 3 ) (3, 3) (3,3);
- perform the operation on the cell ( 1 , 1 ) (1, 1) (1,1).
It can be shown that there is no way to convert all elements to 0s in 0 0 0 or 1 1 1 steps, so the answer is exactly 2 2 2.
Tutorial
由题意不难得出,每次反转的范围是以一个点为顶点,以等腰三角形向下延伸的这个三角形区域,所以就需要从第一层到最后一层遍历所有的点一次,遇到一个需要反转的点答案就加一(这一过程有点像 D P DP DP ,但总体来说也算是前缀和?)
在从第一层到最后一层的遍历中,需要将前缀和转换为三个前缀和数组的累加:一个从上到下的前缀和数组、一个从左上到右下的前缀和数组、一个从右上到左下的前缀和数组,从上到下一层一层判断,由于利用到了前缀和数组,所以时间复杂度为 O ( n 2 ) O(n^2) O(n2)
Solution
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int N = 3005;
int a[N][N], b[N][N], c[N][N], d[N][N];
void solve() {
int n ,ans = 0;
cin >> n;
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
for (int j = 0; j < n; ++j) {
a[i][j] = s[j] - '0';
b[i][j] = c[i][j] = d[i][j] = 0;
}
}
for (int x = 0; x < n; ++x) {
for (int y = 0; y < n; ++y) {
if (x > 0) {
b[x][y] ^= b[x - 1][y];
if (y > 0) {
c[x][y] ^= c[x - 1][y - 1];
}
if (y < n - 1) {
d[x][y] ^= d[x - 1][y + 1];
}
}
a[x][y] ^= (b[x][y] ^= c[x][y] ^ d[x][y]);
if (a[x][y]) {
ans++;
b[x][y] ^= 1;
c[x][y] ^= 1;
d[x][y] ^= 1;
}
}
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
int test; cin >> test; while (test--)
solve();
return 0;
}