wsyu24年暑假热身赛第2场题解
A
因为数组在循环位移的过程中,只有满足在非递减数组的情况下才记做一次排序,现在分两种情况来看
\(a\) 为排序后的数组名,\(0\) 为首个下标,\(n - 1\) 为最后一个下标。
- \(a[0] < a[n - 1]\) 进行一次位移操作后 \(a[n - 1]\) 变成 \(a[n - 2]\), \(a[0]\)变成 \(a[n - 1]\), 这时候 \(a[n - 2] > a[n - 1]\) 排序不成立, 后续的排序也一定不成立,一共有能组成 \(1\) 种排列。
- a[0] == a[n] 进行一次位移操作后 \(a[0]\) 变成 \(a[n]\) ,但数值并未发生改变,一共可以有 \(n\) 种排列。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
void solve() {
int n, m;
cin >> n >> m;
if (m == 1) {
for (int i = 1; i <= n; i ++ ) {
cout << i << ' ';
}
} else if (n == m) {
for (int i = 1; i <= n; i ++ ) {
cout << 1 << ' ';
}
} else {
cout << -1;
}
cout << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt = 1;
cin >> tt;
while (tt--) {
solve();
}
return 0;
}
B
把一个数 \(x\) 由 \(2^i\) 表示出来,可以看出这是一道将 \(x\) 转成二进制来计算的题,但由于题目要求连续的两个数必须要有一个为 \(0\), 现在的问题就变成了,如何将原本的多个\(1\)组成的字符串转换成\(-1\) 和 \(0\)
以下由二进制表示:
(高位) 10011110
(高位) 1010000-10 连续的 \(1\) 可以变成以 $-1 $结尾,首地址前一位改为\(1\),中间为\(0\)的字符串。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
void solve() {
int n;
cin >> n;
vector<int> res;
while (n) {
res.push_back(n & 1);
n >>= 1;
}
for (int i = 0; i < res.size(); i ++ ) {
if (res[i] == 1 && (i + 1 < res.size() && res[i + 1] == 1)) {
int j;
res[i] = -1;
for (j = i + 1; j < res.size() && res[j] == 1; j ++ ) {
res[j] = 0;
}
if (j == res.size()) res.push_back(1);
else res[j] = 1;
i = j - 1;
}
}
cout << res.size() << endl;
for (int i = 0; i < res.size(); i ++ ) {
cout << res[i] << ' ';
}
cout << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt = 1;
cin >> tt;
while (tt--) {
solve();
}
return 0;
}
C
因为没有次数限制,当 \(x > y\) 时所有的门一定会被全部破坏,反之只有小于等于\(x\)且没有被维修过的门才会被破坏。记录小于等于 \(x\) 的数量除 \(2\) ,由于是先破坏再修补所以是上取整。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int n, x, y;
int res;
int main() {
cin >> n >> x >> y;
for (int i = 0; i < n; i ++ ) {
int t;
cin >> t;
if (t <= x) res ++ ;
}
if (x > y) cout << n << endl;
else cout << (res + 1) / 2 << endl;
return 0;
}
D
当字符为"^"时特判,如果当前符号位'_'且前面缺少'^'时需要补充,结尾如果不是'^'时计数增加1。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
void solve() {
string s;
cin >> s;
int res = 0;
if (s == "^") {
cout << 1 << endl;
return;
}
for (int i = 0; i < s.size(); i ++ ) {
if ((i == 0 || s[i - 1] != '^') && s[i] == '_')
res ++ ;
}
if (s.back() == '_') res ++ ;
cout << res << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt = 1;
cin >> tt;
while (tt--) {
solve();
}
return 0;
}
E
当 \(l != r\) 由于最小的非 \(1gcd\) 值是 \(2\) ,所以只要能组合成两个偶数就可以满足条件。
\(r - 1 >= l\) 且 \(r - 2 > 0\) 即可
当 \(l == r\) 时寻找 \(l\) 的所有因子 \(x\), 当 \(gcd(x, l - x) != 1\) 且 \((l - x != 0)\)时输出即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
void solve() {
int l, r;
cin >> l >> r;
if (l == r) {
for (int i = 2; i <= sqrt(l); i ++ ) {
if (l % i == 0) { //只有l 和 l - i同时位质数时gcd为1, 但因为l是i的倍数,(l - i)要么等
cout << i << ' ' << l - i << endl; //于i,要么是i的倍数,他们的gcd值一定不为1。
return;
}
}
cout << -1 << endl;
} else {
if (r % 2) r -- ;
if (r - 2 > 0) {
cout << 2 << ' ' << r - 2 << endl;
} else {
cout << -1 << endl;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt = 1;
cin >> tt;
while (tt--) {
solve();
}
return 0;
}
F
统计不是第一次遇到的数字的个数,这就是要删掉的个数,由于一次删除两个数字,多余的操作在结果上减去即可(存在多余操作,一定会删掉非重复数字,使结果减少)。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
void solve() {
int n, res = 0;
set<int> q;
cin >> n;
while (n -- ) {
int x;
cin >> x;
if (q.count(x)) res ++ ;
q.insert(x);
}
cout << q.size() - res % 2 << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt = 1;
cin >> tt;
while (tt--) {
solve();
}
return 0;
}