Codeforces Round #631 (Div. 2) - Thanks, Denis aramis Shitov!题解

在这里插入图片描述
写在前面: 只过了2题,希望以后能真真实实过多一点!!!

A. Dreamoon and Ranking Collection

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Dreamoon is a big fan of the Codeforces contests.

One day, he claimed that he will collect all the places from 1 to 54 after two more rated contests. It’s amazing!

Based on this, you come up with the following problem:

There is a person who participated in n Codeforces rounds. His place in the first round is a1, his place in the second round is a2, …, his place in the n-th round is an.

You are given a positive non-zero integer x.

Please, find the largest v such that this person can collect all the places from 1 to v after x more rated contests.

In other words, you need to find the largest v, such that it is possible, that after x more rated contests, for each 1≤i≤v, there will exist a contest where this person took the i-th place.

For example, if n=6, x=2 and a=[3,1,1,5,7,10] then answer is v=5, because if on the next two contest he will take places 2 and 4, then he will collect all places from 1 to 5, so it is possible to get v=5.

Input
The first line contains an integer t (1≤t≤5) denoting the number of test cases in the input.

Each test case contains two lines. The first line contains two integers n,x (1≤n,x≤100). The second line contains n positive non-zero integers a1,a2,…,an (1≤ai≤100).

Output
For each test case print one line containing the largest v, such that it is possible that after x other contests, for each 1≤i≤v, there will exist a contest where this person took the i-th place.

Example
inputCopy
5
6 2
3 1 1 5 7 10
1 100
100
11 1
1 1 1 1 1 1 1 1 1 1 1
1 1
1
4 57
80 60 40 20
outputCopy
5
101
2
2
60
Note
The first test case is described in the statement.

In the second test case, the person has one hundred future contests, so he can take place 1,2,…,99 and place 101 on them in some order, to collect places 1,2,…,101.
思路: 把他给你的数用完前能从1数到几位。

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
#define endl '\n'
 
ll a[100010];
 
int main()
{
    int t;
    cin >> t;
 
    while (t--)
    {
        int n, x;
        cin >> n >> x;
        map<int, int>k;
        for (int i = 0; i < n; ++i)
        {
            int kk;
            cin >> kk;
            k[kk] = 1;
        }
        int ans = 0;
        int num = x;
        for (int i = 1;; ++i)
        {
            if (k[i] != 1 && x == 0) break;
            if (k[i] == 1)
            {
                ans++;
            }
            else
            {
                x--;
                ans++;
            }
        }
        cout << ans << endl;
    }
 
    return 0;
}

B. Dreamoon Likes Permutations

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
The sequence of m integers is called the permutation if it contains all integers from 1 to m exactly once. The number m is called the length of the permutation.

Dreamoon has two permutations p1 and p2 of non-zero lengths l1 and l2.

Now Dreamoon concatenates these two permutations into another sequence a of length l1+l2. First l1 elements of a is the permutation p1 and next l2 elements of a is the permutation p2.

You are given the sequence a, and you need to find two permutations p1 and p2. If there are several possible ways to restore them, you should find all of them. (Note that it is also possible that there will be no ways.)

Input
The first line contains an integer t (1≤t≤10000) denoting the number of test cases in the input.

Each test case contains two lines. The first line contains one integer n (2≤n≤200000): the length of a. The second line contains n integers a1,a2,…,an (1≤ai≤n−1).

The total sum of n is less than 200000.

Output
For each test case, the first line of output should contain one integer k: the number of ways to divide a into permutations p1 and p2.

Each of the next k lines should contain two integers l1 and l2 (1≤l1,l2≤n,l1+l2=n), denoting, that it is possible to divide a into two permutations of length l1 and l2 (p1 is the first l1 elements of a, and p2 is the last l2 elements of a). You can print solutions in any order.

Example
inputCopy
6
5
1 4 3 2 1
6
2 4 1 3 2 1
4
2 1 1 3
4
1 3 3 1
12
2 1 3 4 5 6 7 8 9 1 10 2
3
1 1 1
outputCopy
2
1 4
4 1
1
4 2
0
0
1
2 10
0
Note
In the first example, two possible ways to divide a into permutations are {1}+{4,3,2,1} and {1,4,3,2}+{1}.

In the second example, the only way to divide a into permutations is {2,4,1,3}+{2,1}.

In the third example, there are no possible ways.
思路: 从头找第一个重复的数字,重复的位置就是一个分割点,前面的数字判断合不合法,后面也是。然后从后往前找第一个重复,一样的操作。

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
#define endl '\n'
 
ll a[200010], b[200010];
 
int main()
{
    int t;
    cin >> t;
 
    while (t--)
    {
        int n;
        cin >> n;
        int p1 = 0, p2 = 0;
        map<ll, ll>xx;
        for (int i = 0; i < n; ++i)
        {
            cin >> a[i];
            if (xx[a[i]] == 0)
                xx[a[i]] = 1;
            else if (p1 == 0)
            {
                p1 = i;
            }
            b[i] = a[i];
        }
        map<ll, ll>yy;
        for (int i = n - 1; i >= 0; --i)
        {
            if (yy[a[i]] != 1)
                yy[a[i]] = 1;
            else
            {
                p2 = i;
                break;
            }
        }
 
        int ans = 0;
        if (p1 == 0)
        {
            cout << ans << endl;
            continue;
        }
        sort(a, a + p1);
        sort(a + p1, a + n);
        int f1 = 0, f2 = 0;
        if (a[0] != 1) f1 = 1;
        for (int i = 1; i < p1; ++i)
        {
            if (a[i] != a[i - 1] + 1)
            {
                f1 = 1;
            }
            if (f1) break;
        }
        if (a[p1] != 1) f1 = 1;
        for (int i = p1 + 1; i < n; ++i)
        {
            if (a[i] != a[i - 1] + 1)
                f1 = 1;
            if (f1) break;
        }
        if (!f1) ans++;
 
        sort(b, b + p2 + 1);
        sort(b + p2 + 1, b + n);
        if (b[0] != 1) f2 = 1;
        for (int i = 1; i <= p2; ++i)
        {
            if (b[i] != b[i - 1] + 1)
            {
                f2 = 1;
            }
            if (f2) break;
        }
        if (b[p2 + 1] != 1) f2 = 1;
        for (int i = p2 + 2; i < n; ++i)
        {
            if (b[i] != b[i - 1] + 1)
                f2 = 1;
            if (f2) break;
        }
        if (!f2) ans++;
        if (p1 == p2 + 1 && f1 == 0 && f2 == 0)
        {
            ans--;
            f2 = 1;
        }
        cout << ans << endl;
        if (!f1)
            cout << p1 << " " << n - p1 << endl;
        if (!f2)
            cout << p2 + 1 << " " << n - p2 - 1 << endl;
    }
 
    return 0;
}

C. Dreamoon Likes Coloring

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Dreamoon likes coloring cells very much.

There is a row of n cells. Initially, all cells are empty (don’t contain any color). Cells are numbered from 1 to n.

You are given an integer m and m integers l1,l2,…,lm (1≤li≤n)

Dreamoon will perform m operations.

In i-th operation, Dreamoon will choose a number pi from range [1,n−li+1] (inclusive) and will paint all cells from pi to pi+li−1 (inclusive) in i-th color. Note that cells may be colored more one than once, in this case, cell will have the color from the latest operation.

Dreamoon hopes that after these m operations, all colors will appear at least once and all cells will be colored. Please help Dreamoon to choose pi in each operation to satisfy all constraints.

Input
The first line contains two integers n,m (1≤m≤n≤100000).

The second line contains m integers l1,l2,…,lm (1≤li≤n).

Output
If it’s impossible to perform m operations to satisfy all constraints, print “’-1” (without quotes).

Otherwise, print m integers p1,p2,…,pm (1≤pi≤n−li+1), after these m operations, all colors should appear at least once and all cells should be colored.

If there are several possible solutions, you can print any.

Examples
inputCopy
5 3
3 2 2
outputCopy
2 4 1
inputCopy
10 1
1
outputCopy
-1
思路: 每次都把对应一位涂上色。

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
#define endl '\n'
 
ll a[200010], b[200010];
 
int main()
{
    int n, m;
    cin >> n >> m;
 
    for (int i = 1; i <= m; ++i) cin >> a[i];
 
    int pos = n + 1;
 
    for (ll i = m; i >= 0; --i)
    {
        int k = max(pos - a[i], i);
        if (k < i || k > n - a[i] + 1)
        {
            cout << "-1";
            return 0;
        }
        b[i] = k;
        pos = k;
    }
 
    if (pos > 1)
    {
        cout << "-1";
        return 0;
    }
 
    for (int i = 1; i <= m; ++i)
        cout << b[i] << " ";
 
    return 0;
}

D. Dreamoon Likes Sequences

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Dreamoon likes sequences very much. So he created a problem about the sequence that you can’t find in OEIS:

You are given two integers d,m, find the number of arrays a, satisfying the following constraints:

The length of a is n, n≥1
1≤a1<a2<⋯<an≤d
Define an array b of length n as follows: b1=a1, ∀i>1,bi=bi−1⊕ai, where ⊕ is the bitwise exclusive-or (xor). After constructing an array b, the constraint b1<b2<⋯<bn−1<bn should hold.
Since the number of possible arrays may be too large, you need to find the answer modulo m.

Input
The first line contains an integer t (1≤t≤100) denoting the number of test cases in the input.

Each of the next t lines contains two integers d,m (1≤d,m≤109).

Note that m is not necessary the prime!

Output
For each test case, print the number of arrays a, satisfying all given constrains, modulo m.

Example
inputCopy
10
1 1000000000
2 999999999
3 99999998
4 9999997
5 999996
6 99995
7 9994
8 993
9 92
10 1
outputCopy
1
3
5
11
17
23
29
59
89
0

思路: 长度不确定!!!

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
#define endl '\n'
 
ll a[200010], b[200010];
 
int main()
{
    int test;
    cin >> test;
    while (test--)
    {
        ll n, mod;
 
        cin >> n >> mod;
 
        ll t = 1, ans = 1 % mod;
        while (n > 0)
        {
            ans = ans * (min(n, t) + 1) % mod;
            n -= min(n, t);
            t *= 2;
        }
        cout << (ans - 1 + mod) % mod << endl;
    }
 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值