A - 小紅喜歡1
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
for(int i = 1 , x ; i <= 5 ; i ++) {
cin >> x;
if(x == 1) cout << i;
}
return 0;
}
B - 小紅的樹切割
要切割的邊,端點一定同色。
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
string s;
cin >> s;
int cnt = 0;
for (int i = 1, x, y; i < n; i++) {
cin >> x >> y, x--, y--;
if(s[x] == s[y]) cnt ++;
}
cout << cnt;
return 0;
}
C - 小紅的雙好數(easy)
二進位制下,一定只有 \(0\) 和 \(1\)。\(n\)進位制下,一定是\(10\)
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
bool check(int x, int y) {
while (x) {
if (x % y > 1) return false;
x /= y;
}
return true;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
i64 n;
cin >> n;
if (n == 1) cout << "YES\n2 3\n";
else if (n == 2) cout << "NO\n";
else cout << "YES\n2 " << n << "\n";
return 0;
}
D - 小紅的線段
點可以分成三種,\(y > kx + b , y = kx + b , y < kx + b\)。然後需要有交點的,最優解是選擇一個大於的和一個小於的,其次是選擇一個大於(小於)和等於,最後是兩個等於,剩餘的情況怎麼連線都沒有交點,所以隨便連就好了。
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, k, b;
cin >> n >> k >> b;
vi A, B, C;
for (int i = 1, N = n * 2, x, y, yy; i <= N; i++) {
cin >> x >> y;
yy = k * x + b;
if (y == yy) C.push_back(i);
else if (y > yy) A.push_back(i);
else B.push_back(i);
}
vector<pii> res;
while (not A.empty() and not B.empty()) {
res.emplace_back(A.back(), B.back());
A.pop_back(), B.pop_back();
}
while (not A.empty() and not C.empty()) {
res.emplace_back(A.back(), C.back());
A.pop_back(), C.pop_back();
}
while (not C.empty() and not B.empty()) {
res.emplace_back(C.back(), B.back());
C.pop_back(), B.pop_back();
}
assert(C.size() % 2 == 0);
for (int i = 1; i < C.size(); i += 2)
res.emplace_back(C[i - 1], C[i]);
cout << res.size() << "\n";
for (auto &[x, y]: res) cout << x << " " << y << " Y\n";
for (int i = 1; i < A.size(); i += 2)
cout << A[i - 1] << " " << A[i] << " N\n";
for (int i = 1; i < B.size(); i += 2)
cout << B[i - 1] << " " << B[i] << " N\n";
return 0;
}
E - 小紅的雙好數(hard)
列舉\(k2\)進位制下只有\(0,1\)的數,然後驗證\(k1\)進位制下即可。複雜度\(O(2^{18\times\log_{k2} 10})\)
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int k1, k2;
cin >> k1 >> k2;
int N = 1e18;
vi p(1, 1);
while (p.back() * k2 <= N)
p.push_back(p.back() * k2);
auto check = [k1](int x) {
if (x < 2) return false;
while (x) {
if (x % k1 > 1) return false;
x /= k1;
}
return true;
};
auto dfs = [p, check, N](auto &&self, int x, int i) -> void {
if (x > N) return;
if (check(x)) {
cout << "YES\n" << x << "\n";
exit(0);
}
if (i == p.size()) return;
self(self, x, i + 1);
self(self, x + p[i], i + 1);
return;
};
dfs(dfs, 0, 0);
cout << "NO\n";
return 0;
}
F - 小紅的陣列操作
每個陣列的最小值可以用std::multiset<int>
維護。
字首最小值可以用線段樹維護。
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
struct Node {
int l, r, value;
Node *left, *right;
Node(int l, int r, int value, Node *left, Node *right) :
l(l), r(r), value(value), left(left), right(right) {};
};
// 建樹
Node *build(int l, int r, const vi &arr) {
if (l == r) return new Node(l, r, arr[l], nullptr, nullptr);
int mid = (l + r) >> 1;
Node *left = build(l, mid, arr), *right = build(mid + 1, r, arr);
return new Node(l, r, min(left->value, right->value), left, right);
}
// 修改
void modify(int l, int r, int v, Node *cur) {
if (l > cur->r || r < cur->l) return;
if (l <= cur->l && r >= cur->r) {
cur->value = v;
return;
}
int mid = (cur->l + cur->r) >> 1;
if (l <= mid) modify(l, r, v, cur->left);
if (r > mid) modify(l, r, v, cur->right);
cur->value = min(cur->left->value, cur->right->value);
return;
}
// 查詢
int query(int l, int r, Node *cur) {
if (l <= cur->l && r >= cur->r) return cur->value;
int mid = (cur->l + cur->r) >> 1, res = inf;
if (l <= mid) res = min(res, query(l, r, cur->left));
if (r > mid) res = min(res, query(l, r, cur->right));
return res;
}
void modify(int x, int v, Node *cur) {
modify(x, x, v, cur);
}
int query(int x, Node *cur) {
return query(1, x, cur);
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
vector<vi> a(n + 1);
vector<multiset<int>> calc(n + 1);
vi arr(n + 1);
for (int i = 1, m; i <= n; i++) {
cin >> m;
a[i] = vi(m + 1);
for (int j = 1; j <= m; j++)
cin >> a[i][j], calc[i].insert(a[i][j]);
arr[i] = *calc[i].begin();
}
Node *root = build(1, n, arr);
int q;
cin >> q;
for (int opt, i, j, x; q; q--) {
cin >> opt;
if (opt == 1) {
cin >> i >> j >> x;
calc[i].erase(calc[i].find(a[i][j]));
a[i][j] = x, calc[i].insert(x);
if (*calc[i].begin() != arr[i])
arr[i] = *calc[i].begin(), modify(i, arr[i], root);
} else {
cin >> i;
cout << query(i, root) << "\n";
}
}
return 0;
}
G - 小紅的雙排列構造
在大多數情況下是存在無解的情況,大致的構造思路是
\[1,2,3\dots,n,1,2,3,\dots, k - 2 , n , n - 1 , n - 2 , \dots,k - 1
\]
下面說一下幾種特例。
- \(n=1\)時,只有\(1,1\)一種情況
- \(k = 2\)時,\(1,1\)是唯一解
- 其他情況均無解
- \(n=2\)時
- \(k=1\)時,\(1,1,2,2\)
- \(k=2\)時,\(1,2,2,1\)
- \(k=3\)時,\(1,2,1,2\)
- 其他情況無解
- 其他情況下,不會出現無解的情況,但依舊有特例
- \(k=0\)時,\(1,1,2,2,3,3\dots,n,n\)
- \(k = 1\)時,\(1,1,2,3,\dots,n,2,3,4,\dots,n\)
- \(k=2\)時,\(1,2,3,\dots,n,n,n-1,n-2,n-3,\dots,1\)
#include<bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using i128 = __int128;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = INT_MAX / 2;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, k;
cin >> n >> k;
if (n == 1) {
if (k == 2) cout << "1 1";
else cout << "-1";
} else if (n == 2) {
if (k == 1)cout << "1 1 2 2";
else if (k == 3) cout << "1 2 1 2";
else if (k == 2) cout << "1 2 2 1";
else cout << "-1";
} else if (k == 0) {
for (int i = 1; i <= n; i++)
cout << i << " " << i << " ";
} else if (k == 1) {
cout << 1 << " ";
for (int i = 1; i <= n; i++)
cout << i << " ";
for (int i = 2; i <= n; i++)
cout << i << " ";
} else if (k == 2) {
for (int i = 1; i <= n; i++)
cout << i << " ";
for (int i = n; i >= 1; i--)
cout << i << " ";
} else {
for (int i = 1; i <= n; i++)
cout << i << " ";
for (int i = 1; i <= k - 2; i++)
cout << i << " ";
for (int i = n; i > k - 2; i--)
cout << i << " ";
}
return 0;
}