Codeforces Round #786 (Div. 3)

CF系列题解


题目

A. Number Transformation

原题链接

A. Number Transformation

题意

给定 x , y x,y x,y,求一对正整数对 a , b a,b a,b 使得 x ⋅ b a = y x⋅b^a = y xba=y

输入格式
第一行包含一个整数 t ( 1 ≤ t ≤ 1 0 4 ) t (1≤t≤10^4) t(1t104) ,表示有t组测试数据。
每个测试数据第一行包含两个整数 x , y ( 1 ≤ x , y ≤ 100 ) x, y (1≤x,y≤100) x,y(1x,y100)

输出格式
满足条件的正整数 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

原题链接

B - Dictionary

题意

一个字符串集合的所有字符串是由两个小写字母组成,将该集合按照字典序排序,每个字符串都会有一个排名,每次给定一个字符串 s s s,求 s s s 的排名。

输入格式
第一行包含一个整数 t ( 1 ≤ t ≤ 650 ) t (1≤t≤650) t(1t650) ,表示有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

原题链接

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(1q104) ,表示有q组测试数据。
每个测试数据包含两个字符串 s , t s,t s,t,长度不超过 50 50 50

输出格式
方案数

输入样例:

3
aaaa
a
aa
abc
a
b

输出样例:

1
-1
2

题解

思路

分类讨论。

  1. t t t"a",那么每次替换都没有影响,因此答案为 1 1 1
  2. t t t 中含有 a,那么就会形成套娃,因此答案为无穷大。
  3. 否则说明 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

原题链接

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(1t2104) ,表示有 t t t 组测试数据。
每个测试数据第一行包含一个整数 n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n (1≤n≤2⋅10^5) n(1n2105),表示数组长度。
第二行包含 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(1ai106)
n n n 的总和不超过 2 ⋅ 1 0 5 2⋅10^5 2105

输出格式
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} an1 在插入 b b b 之后必定是成对弹出 b b b 的,因此在 c c c 中能被改变顺序的只有 [ a n , a n − 1 ] [a_n,a_{n-1}] [an,an1] [ a n − 2 , a n − 3 ] [a_{n-2},a_{n-3}] [an2,an3] [ a n − 4 , a n − 5 ] [a_{n-4},a_{n-5}] [an4,an5],…

因此我们只需枚举这样的点对使得其成不降点对,然后枚举 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代码)

原题链接

E. Breaking the Wall

题意

输入格式

输出格式

输入样例:

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值