CF系列题解
Codeforces Round #786 (Div. 3)
题目
A. Number Transformation
原题链接
题意
给定 x , y x,y x,y,求一对正整数对 a , b a,b a,b 使得 x ⋅ b a = y x⋅b^a = y x⋅ba=y。
输入格式
第一行包含一个整数
t
(
1
≤
t
≤
1
0
4
)
t (1≤t≤10^4)
t(1≤t≤104) ,表示有t组测试数据。
每个测试数据第一行包含两个整数
x
,
y
(
1
≤
x
,
y
≤
100
)
x, y (1≤x,y≤100)
x,y(1≤x,y≤100)。
输出格式
满足条件的正整数
a
,
b
a,b
a,b。
输入样例:
3
3 75
100 100
42 13
输出样例:
2 5
3 1
0 0
题解
思路
首先 y y y 能整除 x x x,直接让 a = 1 , b = y / x a=1,b=y/x a=1,b=y/x 即可。
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve()
{
int x, y;
cin >> x >> y;
if (x > y || y % x) {
cout << "0 0\n";
return;
}
cout << 1 << " " << y / x << "\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}
B - Dictionary
原题链接
题意
一个字符串集合的所有字符串是由两个小写字母组成,将该集合按照字典序排序,每个字符串都会有一个排名,每次给定一个字符串 s s s,求 s s s 的排名。
输入格式
第一行包含一个整数
t
(
1
≤
t
≤
650
)
t (1≤t≤650)
t(1≤t≤650) ,表示有t组测试数据。
每个测试数据包含一个字符串
s
s
s,
s
s
s由两个不同的字符组成。
输出格式
输出该字符串的字典序排名。
输入样例:
7
ab
ac
az
ba
bc
zx
zy
输出样例:
1
2
25
26
27
649
650
题解
思路
暴力预处理然后查询即可。
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
map<string, int> mp;
void init()
{
int idx = 0;
for (char a = 'a'; a <= 'z'; a ++ ) {
for (char b = 'a'; b <= 'z'; b ++ ) {
if (a != b) {
string s;
s += a;
s += b;
mp[s] = ++ idx;
}
}
}
}
void solve()
{
string s;
cin >> s;
cout << mp[s] << "\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}
C - Infinite Replacement
原题链接
题意
给定一个全部由 a
组成的字符串
s
s
s 和一个任意的字符串
t
t
t,每次可以把
s
s
s 中的 a
换成
t
t
t,求能组成多少种不同的字符串(原串也算)。
输入格式
第一行包含一个整数
q
(
1
≤
q
≤
1
0
4
)
q (1≤q≤10^4)
q(1≤q≤104) ,表示有q组测试数据。
每个测试数据包含两个字符串
s
,
t
s,t
s,t,长度不超过
50
50
50。
输出格式
方案数
输入样例:
3
aaaa
a
aa
abc
a
b
输出样例:
1
-1
2
题解
思路
分类讨论。
- 若
t
t
t 为
"a"
,那么每次替换都没有影响,因此答案为 1 1 1。 - 若
t
t
t 中含有
a
,那么就会形成套娃,因此答案为无穷大。 - 否则说明 s s s 的每个位置均可以替换,设 s s s 的长度为 n n n,因此方案书为 C n 0 + C n 1 + C n 2 + . . . + C n n = 2 n C_n^0+C_n^1+C_n^2+...+C_n^n=2^n Cn0+Cn1+Cn2+...+Cnn=2n,杨辉三角。
会爆 i n t int int。
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve()
{
string s, t;
cin >> s >> t;
if (t == "a") {
cout << "1\n";
} else {
int cnt = 0;
for (int i = 0; i < t.size(); i ++ ) {
cnt += (t[i] == 'a');
}
if (cnt) {
cout << "-1\n";
} else {
cout << (1ll << (int)s.size()) << "\n";
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}
D. A-B-C Sort
原题链接
题意
给定一个数组 a a a, b , c b,c b,c 为空数组。
操作1:把
a
a
a 数组从末尾开始往
b
b
b 中间插,若
b
b
b 中有奇数个数,选择中间数的任意两边。
操作2:把
b
b
b 数组的数从中间开始往
c
c
c 的末尾开始插。
问最终的 c c c 是否为不降序列。
注意: 此处操作应该是先全部进行完操作1后再进行操作2。
输入格式
第一行包含一个整数
t
(
1
≤
t
≤
2
⋅
1
0
4
)
t (1≤t≤2⋅10^4)
t(1≤t≤2⋅104) ,表示有
t
t
t 组测试数据。
每个测试数据第一行包含一个整数
n
(
1
≤
n
≤
2
⋅
1
0
5
)
n (1≤n≤2⋅10^5)
n(1≤n≤2⋅105),表示数组长度。
第二行包含
n
n
n 个整数
a
1
,
a
2
,
…
,
a
n
(
1
≤
a
i
≤
1
0
6
)
a_1,a_2,…,a_n (1≤a_i≤10^6)
a1,a2,…,an(1≤ai≤106)。
n
n
n 的总和不超过
2
⋅
1
0
5
2⋅10^5
2⋅105。
输出格式
c
c
c 是否不降,是的话输出 YES
,不是的话输出 NO
。
输入样例:
3
4
3 1 5 3
3
3 2 1
1
7331
输出样例:
YES
NO
YES
题解
思路
我们发现每次插入都是成对插入 b b b 并且成对插入 c c c 的,即 a n a_n an 和 a n − 1 a_{n-1} an−1 在插入 b b b 之后必定是成对弹出 b b b 的,因此在 c c c 中能被改变顺序的只有 [ a n , a n − 1 ] [a_n,a_{n-1}] [an,an−1], [ a n − 2 , a n − 3 ] [a_{n-2},a_{n-3}] [an−2,an−3], [ a n − 4 , a n − 5 ] [a_{n-4},a_{n-5}] [an−4,an−5],…
因此我们只需枚举这样的点对使得其成不降点对,然后枚举 a a a 看其是否不降即可。
STLyyds!!!
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = n - 1; i - 1 >= 0; i -= 2) {
if (a[i] < a[i - 1]) swap(a[i], a[i - 1]);
}
if (is_sorted(a.begin(), a.end())) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}
E. Breaking the Wall(先贴一个shit代码)
原题链接
题意
输入格式
输出格式
输入样例:
5
20 10 30 10 20
输出样例:
10
输入样例:
3
1 8 1
输出样例:
1
输入样例:
6
7 6 6 8 5 8
输出样例:
4
输入样例:
6
14 3 8 10 15 4
输出样例:
4
输入样例:
4
1 100 100 1
输出样例:
2
输入样例:
3
40 10 10
输出样例:
7
题解
思路
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
int cost1 = 1e9, cost2 = 1e9;
for (int i = 0; i < n; i ++ ) {
int cost = ceil(a[i] / 2.0);
if (cost < cost1) cost2 = cost1, cost1 = cost;
else if (cost < cost2) cost2 = cost;
}
int ans = cost1 + cost2;
for (int i = 0; i < n - 1; i ++ ) {
int k1 = ceil(a[i] / 3.0);
int k2 = ceil(a[i + 1] / 3.0);
int k3 = 0;
if (k1 > k2) {
k3 += ceil((a[i] - 3 * k2) / 2.0);
ans = min(ans, k2 * 2 + k3);
} else if (k1 < k2) {
k3 += ceil((a[i + 1] - 3 * k1) / 2.0);
ans = min(ans, k1 * 2 + k3);
} else {
ans = min(ans, k1 * 2);
}
}
for (int i = 0; i < n - 1; i ++ ) {
int k1 = ceil((a[i] - 1) / 3.0);
int k2 = ceil((a[i + 1] - 2) / 3.0);
int k3 = 0;
if (k1 > k2) {
k3 += ceil((a[i] - 3 * k2) / 2.0);
ans = min(ans, k2 * 2 + k3 + 1);
} else if (k1 < k2) {
k3 += ceil((a[i + 1] - 3 * k1) / 2.0);
ans = min(ans, k1 * 2 + k3 + 1);
} else {
ans = min(ans, k1 * 2 + 1);
}
}
for (int i = 0; i < n - 1; i ++ ) {
int k = abs(a[i] - a[i + 1]);
int x = max(a[i], a[i + 1]);
int y = min(a[i], a[i + 1]);
int k1 = ceil(x / 2.0);
int k2 = ceil(y / 1.0);
x -= min({k2, k1, k}) * 2;
y -= min({k2, k1, k}) * 1;
if (x == y) {
if (x % 3 == 0) {
ans = min(ans, k + x / 3 * 2);
} else if (x % 3 == 1) {
ans = min(ans, k + x / 3 * 2 + 1);
} else {
ans = min(ans, k + x / 3 * 2 + 2);
}
} else {
ans = min(ans, k2 + (int)ceil(x / 2.0));
}
}
for (int i = 0; i < n - 1; i ++ ) {
int k1 = ceil((a[i] - 2) / 3.0);
int k2 = ceil((a[i + 1] - 1) / 3.0);
int k3 = 0;
if (k1 > k2) {
k3 += ceil((a[i] - 3 * k2) / 2.0);
ans = min(ans, k2 * 2 + k3 + 1);
} else if (k1 < k2) {
k3 += ceil((a[i + 1] - 3 * k1) / 2.0);
ans = min(ans, k1 * 2 + k3 + 1);
} else {
ans = min(ans, k1 * 2 + 1);
}
}
for (int i = 0; i + 2 < n; i ++ ) {
int x = a[i], y = a[i + 2];
if (x > y) swap(x, y);
ans = min(ans, x + (int)ceil((y - x) / 2.0));
}
auto check = [&](int k) {
int k1 = ceil(a[0] / 2.0);
if (a[1] - k1 > 0) k1 += ceil((a[1] - k1) / 2.0);
if (k1 <= k) return true;
int k2 = ceil(a[n - 1] / 2.0);
if (a[n - 2] - k2 > 0) k2 += ceil((a[n - 2] - k2) / 2.0);
if (k2 <= k) return true;
for (int i = 1; i < n - 1; i ++ ) {
if (max(a[i - 1], a[i + 1]) <= k) return true;
int k3 = ceil(a[i] / 2.0);
int k4 = k3;
if (a[i - 1] - k3 > 0) k3 += ceil((a[i - 1] - k3) / 2.0);
if (k3 <= k) return true;
if (a[i + 1] - k4 > 0) k4 += ceil((a[i + 1] - k4) / 2.0);
if (k4 <= k) return true;
}
return false;
};
int l = 1, r = 1e9;
while (l < r) {
int mid = l + r + 1 >> 1;
if (!check(mid)) l = mid;
else r = mid - 1;
}
if (!check(r)) r ++ ;
cout << min(ans, r) << "\n";
return 0;
}