Codeforces Round #550 (Div.3) 题目 & 题解

我的个人Blog,更多题解及算法详解:https://www.beiyanpiki.cn/

CodeForces Contest: http://codeforces.com/contest/977
Probelm Set PDF: https://file.beiyanpiki.cn/ACM/Codeforces%23479.pdf
官方英文题解: http://codeforces.com/blog/entry/59281

A. Wrong Subtraction

Little girl Tanya is learning how to decrease a number by one, but she does it wrong with a number consisting of two or more digits. Tanya subtracts one from a number by the following algorithm:

  • if the last digit of the number is non-zero, she decreases the number by one;
  • if the last digit of the number is zero, she divides the number by 10 (i.e. removes the last digit).

You are given an integer number n n n. Tanya will subtract one from it k k k times. Your task is to print the result after all k k k subtractions.
It is guaranteed that the result will be positive integer number.

input

The first line of the input contains two integer numbers n and k 2 ≤ n ≤ 1 0 9 2 \le n \le 10^9 2n109 — the number from which Tanya will subtract and the number of subtractions correspondingly.

output

Print one integer number — the result of the decreasing n n n by one k k k times.

It is guaranteed that the result will be positive integer number.

Examples

case 1:
inputoutput
512 450
case 2:
inputoutput
1000000000 91

Note

The first example corresponds to the following sequence: 512 → 511 → 510 → 51 → 50 512 \rightarrow 511 \rightarrow 510 \rightarrow 51 \rightarrow 50 5125115105150.


Solve

这是一道500分的签到题。
官方标签:implementation

题意很简单,给出两个数n, k,同时定义一个操作:

  • 当一个数末尾为非零时,该数-1,
  • 当末尾是零时,该数去除最后一个零。

问:一个数n经过k次操作后,n为几。

只需要简单的循环即可得出答案

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    // freopen("in","r",stdin);
    // freopen("out","w",stdout);

    int a;
    int n;
    cin >> a >> n;
    while (n--) {
        if (a % 10 == 0) {
            a /= 10;
        } else {
            a--;
        }
    }
    cout << a << endl;
    return 0;
}

B. Two-gram

Two-gram is an ordered pair (i.e. string of length two) of capital Latin letters. For example, “AZ”, “AA”, “ZA” — three distinct two-grams.

You are given a string s s s consisting of n n n capital Latin letters. Your task is to find any two-gram contained in the given string as a substring (i.e. two consecutive characters of the string) maximal number of times. For example, for string s s s = “BBAABBBA” the answer is two-gram “BB”, which contained in s s s three times. In other words, find any most frequent two-gram.

Note that occurrences of the two-gram can overlap with each other.

input

The first line of the input contains integer number n n n ( 2 ≤ n ≤ 100 2 \le n \le 100 2n100) — the length of string s s s. The second line of the input contains the string s s s consisting of n n n capital Latin letters.

output

Print the only line containing exactly two capital Latin letters — any two-gram contained in the given string s s s as a substring (i.e. two consecutive characters of the string) maximal number of times.

Examples

case 1:
inputoutput
7
ABACABA
AB

####case 2:

inputoutput
5
ZZZAA
ZZ

Note

In the first example “BA” is also valid answer.

In the second example the only two-gram “ZZ” can be printed because it contained in the string “ZZZAA” two times.


Solve

这是一道900分的字符串题。
官方标签:implementationstrings

给出一个字符串长度n和字符串s,求该字符串出现频率最高的子串(子串长度为2)。
比如字符串 “ABC” 中含有两个子串“AB”,“BC”。

这题使用string和map即可快速得出结果。

#include <bits/stdc++.h>

using namespace std;

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    // freopen("in","r",stdin);
    // freopen("out","w",stdout);

    int n;
    string s;
    cin >> n >> s;
    map<string, int> m;
    for (int i = 0; i < n - 1; i++) {
        string ss = s.substr(i, 2);
        m[ss]++;
    }

    map<string, int>::iterator it, maxx;
    maxx = m.begin();
    for (it = m.begin(); it != m.end(); it++) {
        if (it->second > maxx->second) {
            maxx = it;
        }
    }
    cout << maxx->first << endl;

    return 0;
}

C. Less or Equal

You are given a sequence of integers of length n n n and integer number k k k. You should print any integer number x x x in the range of [ 1 ; 1 0 9 ] [1; 10^9] [1;109] (i.e. 1 ≤ x ≤ 1 0 9 1 \le x \le 10^9 1x109) such that exactly k k k elements of given sequence are less than or equal to x x x.

Note that the sequence can contain equal elements.

If there is no such x x x, print “-1” (without quotes).

input

The first line of the input contains integer numbers n n n and k k k ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1n2105, 0 ≤ k ≤ n 0 \le k \le n 0kn). The second line of the input contains n n n integer numbers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109) — the sequence itself.

output

Print any integer number x x x from range [ 1 ; 1 0 9 ] [1; 10^9] [1;109] such that exactly k k k elements of given sequence is less or equal to x x x.

If there is no such x x x, print “-1” (without quotes).

Examples

case 1:
inputoutput
7 4
3 7 5 1 10 3 20
6
case 2:
inputoutput
7 2
3 7 5 1 10 3 20
-1

Note

In the first example 5 5 5 is also a valid answer because the elements with indices [ 1 , 3 , 4 , 6 ] [1, 3, 4, 6] [1,3,4,6] is less than or equal to 5 5 5 and obviously less than or equal to 6 6 6.

In the second example you cannot choose any number that only 2 2 2 elements of the given sequence will be less than or equal to this number because 3 3 3 elements of the given sequence will be also less than or equal to this number.


Solve

这是一道1200分的排序题。
官方标签:sortings

给定一个数组长度n和一个数k,接下来一行给你长度为n的数组a[ ]
问:是否存在一个数x,使数列中恰好有k个数小于等于x。

这里直接使用STL函数sort将序列从小到大排,接下来判断即可。

#include <bits/stdc++.h>
using namespace std;
int a[1000000];

int main() {
    int n, k;
    while (cin >> n >> k) {
        for (int i = 0; i < n; i++)
            cin >> a[i];
        sort(a, a + n);
        if (k == 0) {
            if (a[0] <= 1)
                cout << -1 << endl;
            else
                cout << 1 << endl;
        } else {
            if (n == k) {
                cout << a[n - 1] << endl;
            } else if (a[k - 1] < a[k]) {
                cout << a[k - 1] << endl;
            } else {
                cout << -1 << endl;
            }
        }
    }
    return 0;
}

D. Divide by three, multiply by two

Polycarp likes to play with numbers. He takes some integer number x x x, writes it down on the board, and then performs with it n − 1 n - 1 n1 operations of the two kinds:

  • divide the number x x x by 3 3 3 ( x x x must be divisible by 3 3 3);
  • multiply the number x x x by 2 2 2.

After each operation, Polycarp writes down the result on the board and replaces x x x by the result. So there will be n n n numbers on the board after all.

You are given a sequence of length n n n — the numbers that Polycarp wrote down. This sequence is given in arbitrary order, i.e. the order of the sequence can mismatch the order of the numbers written on the board.

Your problem is to rearrange (reorder) elements of this sequence in such a way that it can match possible Polycarp’s game in the order of the numbers written on the board. I.e. each next number will be exactly two times of the previous number or exactly one third of previous number.

It is guaranteed that the answer exists.

input

The first line of the input contatins an integer number n n n ( 2 ≤ n ≤ 100 2 \le n \le 100 2n100) — the number of the elements in the sequence. The second line of the input contains n n n integer numbers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an ( 1 ≤ a i ≤ 3 ⋅ 1 0 18 1 \le a_i \le 3 \cdot 10^{18} 1ai31018) — rearranged (reordered) sequence that Polycarp can wrote down on the board.

output

Print n n n integer numbers — rearranged (reordered) input sequence that can be the sequence that Polycarp could write down on the board.

It is guaranteed that the answer exists.

Examples

case 1:
inputoutput
6
4 8 6 3 12 9
9 3 6 12 4 8
case 2:
inputoutput
4
42 28 84 126
126 42 84 28
case 3:
inputoutput
2
1000000000000000000 3000000000000000000
3000000000000000000 1000000000000000000

Note

In the first example the given sequence can be rearranged in the following way: [ 9 , 3 , 6 , 12 , 4 , 8 ] [9, 3, 6, 12, 4, 8] [9,3,6,12,4,8]. It can match possible Polycarp’s game which started with x = 9 x = 9 x=9.


Solve

这是一道1400分的题,涉及到深度优先搜索、排序。
官方标签:dfs and similarmathsortings

首先第一行给你一个数组长度n,接下来一行给出一串长度为n的数组a[ ].
问:使该序列按照一定的规则进行排序,规则需要满足以下两条的任意一条

  • a i + 1 = 2 ∗ a i a_{i+1} = 2 * a_i ai+1=2ai
  • a i = 3 ∗ a i + 1 a_{i} = 3 * a_{i+1} ai=3ai+1

题目保证有解

简单的搜索,直接使用深度优先搜索即可,模板题。从 a 0 a_0 a0 a n − 1 a_{n-1} an1,看能否搜到最深处,搜不到立刻剪枝返回上层进行下一个搜索,搜到最底层就直接打印然后退出程序即可。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
ll a[1005];
bool vis[1005];
int n;
bool found = false;
vector<ll> v;

void print() {
    for (int i = 0; i < v.size(); i++) {
        if (i != 0)
            cout << " ";
        cout << v[i];
    }
}

void dfs(int deep, ll last) {
    if (deep == n) {
        print();
        found = true;
        return;
    }
    if (found)
        return;
    for (int i = 0; i < n; i++) {
        if (vis[i])
            continue;
        if ((a[i] / 2 == last && a[i] % 2 == 0) || a[i] * 3 == last) {
            vis[i] = true;
            v.push_back(a[i]);
            dfs(deep + 1, a[i]);
            v.pop_back();
            vis[i] = false;
        }
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    // freopen("in","r",stdin);
    // freopen("out","w",stdout);
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        vis[i] = true;
        v.push_back(a[i]);
        dfs(1, a[i]);
        v.pop_back();
        vis[i] = false;
        if (found)
            break;
    }
    return 0;
}

E. Cyclic Components

You are given an undirected graph consisting of n n n vertices and m m m edges. Your task is to find the number of connected components which are cycles.

Here are some definitions of graph theory.

An undirected graph consists of two sets: set of nodes (called vertices) and set of edges. Each edge connects a pair of vertices. All edges are bidirectional (i.e. if a vertex a a a is connected with a vertex b b b, a vertex b b b is also connected with a vertex a a a). An edge can’t connect vertex with itself, there is at most one edge between a pair of vertices.

Two vertices u u u and v v v belong to the same connected component if and only if there is at least one path along edges connecting u u u and v v v.

A connected component is a cycle if and only if its vertices can be reordered in such a way that:

  • the first vertex is connected with the second vertex by an edge,
  • the second vertex is connected with the third vertex by an edge,
  • the last vertex is connected with the first vertex by an edge,
  • all the described edges of a cycle are distinct.

There are  connected components,  of them are cycles:  and .

A cycle doesn’t contain any other edges except described above. By definition any cycle contains three or more vertices.

input

The first line contains two integer numbers n n n and m m m ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1n2105, 0 ≤ m ≤ 2 ⋅ 1 0 5 0 \le m \le 2 \cdot 10^5 0m2105) — number of vertices and edges.

The following m m m lines contains edges: edge i i i is given as a pair of vertices v i v_i vi, u i u_i ui ( 1 ≤ v i , u i ≤ n 1 \le v_i, u_i \le n 1vi,uin, u i ≠ v i u_i \ne v_i ui̸=vi). There is no multiple edges in the given graph, i.e. for each pair ( v i , u i v_i, u_i vi,ui) there no other pairs ( v i , u i v_i, u_i vi,ui) and ( u i , v i u_i, v_i ui,vi) in the list of edges.

output

Print one integer — the number of connected components which are also cycles.

Examples

case 1:
inputoutput
5 4
1 2
3 4
5 4
3 5
1
case 2:
inputoutput
17 15
1 8
1 12
5 11
11 9
9 15
15 5
4 13
3 13
4 3
10 16
7 10
16 7
14 3
14 4
17 6
2

Note

In the first example only component [ 3 , 4 , 5 ] [3, 4, 5] [3,4,5] is also a cycle.

The illustration above corresponds to the second example.


Solve

这是一道1500分的图论题。
官方标签:dfs and similar dsu graphs

题目说了很长一串,其实目标很简单。给你一对点和一堆边,求出单链环(所有点的度都为2)的个数。
既然求个数,那么这题用并查集做绝对是最方便的选择之一。也是套用模板即可。
前半段常规操作,输入并建立并查集。最后查询个数时只需要查找对应点所在的集合,并将集合中的所有点进行度的计算,只要有一个点的度不为2则不符合单链环要求。

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 200000 + 50;

vector<int> G[MAXN];

int Par[MAXN];
int Rank[MAXN];

void init(int n) {
    for (int i = 0; i < n; i++) {
        Par[i] = i;
        Rank[i] = 0;
    }
}

int Find(int x) {
    if (Par[x] == x) {
        return x;
    } else {
        return Par[x] = Find(Par[x]);
    }
}

void Unite(int x, int y) {
    x = Find(x);
    y = Find(y);
    if (x == y)
        return;
    if (Rank[x] < Rank[y]) {
        Par[x] = y;
    } else {
        Par[y] = x;
        if (Rank[x] == Rank[y])
            Rank[x]++;
    }
}

bool same(int x, int y) { return Find(x) == Find(y); }

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    // freopen("in", "r", stdin);
    // freopen("out","w",stdout);

    int n, T;
    cin >> n >> T;
    for (int i = 0; i < T; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    init(n);
    for (int i = 0; i < T; i++) {
        for (int j = 0; j < G[i].size(); j++) {
            Unite(i, G[i][j]);
        }
    }


    bool vis[MAXN];
    map<int, bool> m;
    int cnt = 0;
    memset(vis, true, sizeof(true));
    for (int i = 0; i < n; i++) {
        int t = Find(i);
        if (m.count(t) == 0)
            m[t] = true;
        if (G[i].size() != 2)
            m[t] = false;
    }
    map<int, bool>::iterator it;
    for (it = m.begin(); it != m.end(); it++) {
        if (it->second)
            cnt++;
    }
    cout << cnt << endl;
    return 0;
}

F. Consecutive Subsequence

You are given an integer array of length n n n.

You have to choose some subsequence of this array of maximum length such that this subsequence forms a increasing sequence of consecutive integers. In other words the required sequence should be equal to [ x , x + 1 , … , x + k − 1 ] [x, x + 1, \dots, x + k - 1] [x,x+1,,x+k1] for some value x x x and length k k k.

Subsequence of an array can be obtained by erasing some (possibly zero) elements from the array. You can erase any elements, not necessarily going successively. The remaining elements preserve their order. For example, for the array [ 5 , 3 , 1 , 2 , 4 ] [5, 3, 1, 2, 4] [5,3,1,2,4] the following arrays are subsequences: [ 3 ] [3] [3], [ 5 , 3 , 1 , 2 , 4 ] [5, 3, 1, 2, 4] [5,3,1,2,4], [ 5 , 1 , 4 ] [5, 1, 4] [5,1,4], but the array [ 1 , 3 ] [1, 3] [1,3] is not.

input

The first line of the input containing integer number n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1n2105) — the length of the array. The second line of the input containing n n n integer numbers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^9 1ai109) — the array itself.

output

On the first line print k k k — the maximum length of the subsequence of the given array that forms an increasing sequence of consecutive integers.

On the second line print the sequence of the indices of the any maximum length subsequence of the given array that forms an increasing sequence of consecutive integers.

Examples

case 1:
inputoutput
7
3 3 4 7 5 6 8
4
2 3 5 6
case 2:
inputoutput
6
1 3 5 2 4 6
2
1 4
case 3:
inputoutput
4
10 9 8 7
1
1
case 4:
inputoutput
9
6 7 8 3 4 5 9 10 11
6
1 2 3 7 8 9

Note

All valid answers for the first example (as sequences of indices):

  • [ 1 , 3 , 5 , 6 ] [1, 3, 5, 6] [1,3,5,6]
  • [ 2 , 3 , 5 , 6 ] [2, 3, 5, 6] [2,3,5,6]

All valid answers for the second example:

  • [ 1 , 4 ] [1, 4] [1,4]
  • [ 2 , 5 ] [2, 5] [2,5]
  • [ 3 , 6 ] [3, 6] [3,6]

All valid answers for the third example:

  • [ 1 ] [1] [1]
  • [ 2 ] [2] [2]
  • [ 3 ] [3] [3]
  • [ 4 ] [4] [4]

All valid answers for the fourth example:

  • [ 1 , 2 , 3 , 7 , 8 , 9 ] [1, 2, 3, 7, 8, 9] [1,2,3,7,8,9]

Solve

这是一道1700分的动态规划题。
官方标签:dp

其实这个动态规划还是挺简单的,类似于求LCS ,只不过这里要求相差1,并且输出下标罢了。
我们可以很轻松的根据题目推出递推公式: d p [ i ] = M A X { d p [ i − 1 ] + 1 , d p [ i ] } dp[i] = MAX \lbrace dp[i - 1] + 1, dp[i] \rbrace dp[i]=MAX{dp[i1]+1,dp[i]}   (ps:额,,,真的不懂这个递推公式的话可以在我的blog留言)

当然,这题的另外一个难点就是存储最长子序列的下标。其实这里可以使用一个投机取巧的方法:首先取出 [ d p , d p n ] [dp , dp_n] [dp,dpn]中最大值和最大值的下标,通过下标得到这个数字a。因为这个最长子序列是相差1,所以我可以直接输出a-dp[maxi] ~ a的所有值。具体可以套样例。

#include <bits/stdc++.h>

using namespace std;

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);

//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);

    int n;
    int a[200000 + 50];
    int maxi = 0;
    int maxdp = 0;
    map<int, int> dp;
    map<int, vector<int>> res;

    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }

    for (int i = 0; i < n; i++) {
        dp[a[i]] = max(dp[a[i] - 1] + 1, dp[a[i]]);
        if (dp[a[i]] > maxdp) {
            maxdp = dp[a[i]];
            maxi = i;
        }
    }
    int cnt = a[maxi] - maxdp + 1;
    cout << maxdp << endl;
    for (int i = 0; i <= maxi; i++) {
        if (a[i] == cnt) {
            cout << i + 1 << " ";
            cnt++;
        }
    }

}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值