Codeforces Round #761 (Div. 2) (A~D2)

Posted by dud3r on Fri, 17 Dec 2021 10:10:12 +0100

Codeforces Round #761 (Div. 2)

A. Forbidden Subsequence

subject

Knowledge points

sort

Problem solving ideas

According to the meaning of the topic, it is easy for us to know when T = a b c T = abc When T=abc and we S S S medium a , b , c a,b,c a. B and C all appear, our youngest S ′ S' S' should be in accordance with a c b d e f g . . . z acbdefg...z acbdefg...z, otherwise it is in dictionary order a b c d e . . . z abcde...z abcde...z .

So we just have to judge T T Whether T is a b c abc abc, S S S medium a , b , c a,b,c a. Whether B and C all appear, and then write the cmp function.

(see code for details)

code

#include <bits/stdc++.h>
#define debug(x) cerr << #x << " = " << x << '\n'
#define between(x, l, r) (x >= l && x <= r)
#define point(a, b, m) ((a - 1) * m + b)
#define all(x) (x).begin(), (x).end()
#define SUM(a) accumulate(all(a), 0LL)
#define MIN(a) (*min_element(all(a)))
#define MAX(a) (*max_element(all(a)))
#define np next_permutation
#define lb lower_bound
#define ub upper_bound
#define eb emplace_back
#define pb push_back
#define y second
#define x first
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;

const int N = 3e5 + 10, M = 2 * N, mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

bool cmp(char a, char b)
{
    if(a == 'b' && b == 'c') return 0;
    if(b == 'b' && a == 'c') return 1;
    return a < b;
}

void solve()
{
    string s, t;
    cin >> s >> t;
    int num[100] = {0};
    for (auto &it : s) num[it - 'a'] ++ ;
    
    if(t == "abc" && num[0] && num[1] && num[2]) sort(all(s), cmp);
    else sort(all(s));
    
    cout << s << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cout.precision(2), cout.setf(ios::fixed);
    int t;
    cin >> t;
    while (t -- )
    solve();
    return 0;
}

B. GCD Problem

subject

Knowledge points

number theory

Problem solving ideas

If n n n is an even number

We can construct c = 1 c = 1 c=1, a = ( n − 1 ) / 2 a = (n - 1) / 2 a=(n−1)/2 , b = n − 1 − a b = n - 1 - a b=n−1−a

Because ∣ a − b ∣ = 1 |a - b| = 1 ∣ a − b ∣ = 1, so g c d ( a , b ) = 1 gcd(a, b) = 1 gcd(a,b)=1

If n n n is an even number

We order c = 1 c = 1 c=1, and then the traversal of violence a , b a, b a. B. find satisfaction g c d ( a , b ) = 1 , a + b = n − 1 gcd(a, b) = 1, a+b=n - 1 A pair of gcd(a,b)=1,a+b=n − 1 ( a , b ) (a, b) (a,b)

We can find out by typing the watch g c d ( a , n − 1 − a ) = 1 gcd(a, n - 1 - a) = 1 The interval between gcd(a,n − 1 − a)=1 will not be too large, so the violence will not timeout.

(see code for details)

code

#include <bits/stdc++.h>
#define debug(x) cerr << #x << " = " << x << '\n'
#define between(x, l, r) (x >= l && x <= r)
#define point(a, b, m) ((a - 1) * m + b)
#define all(x) (x).begin(), (x).end()
#define SUM(a) accumulate(all(a), 0LL)
#define MIN(a) (*min_element(all(a)))
#define MAX(a) (*max_element(all(a)))
#define np next_permutation
#define lb lower_bound
#define ub upper_bound
#define eb emplace_back
#define pb push_back
#define y second
#define x first
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;

const int N = 3e5 + 10, M = 2 * N, mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

/*
gcd(a, b) = c
a + b + c = n
(k + 1) * c == n
c =

If n is even
c = 1
a = (n - 1) / 2
b = n - 1 - a
*/

void solve()
{
    int n;
    cin >> n;
    if(n % 2 == 0)
    {
        int a = (n - 1) / 2, b = n - 1 - a;
        int c = 1;
        cout << a << ' ' << b << ' ' << c << '\n';
    }
    else
    {
        for (int i = 3; i * 2 <= n; i += 2)
        {
            if(__gcd(i, n - 1 - i) != 1 || i == n - 1 - i) continue;
            cout << i << ' ' << n - (1 + i) << ' ' << 1 << '\n';
            return;
        }
    }
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cout.precision(2), cout.setf(ios::fixed);
    int t;
    cin >> t;
    while (t -- )
    solve();
    return 0;
}

C. Paprika and Permutation

subject

Knowledge points

Thinking, greed

Problem solving ideas

This problem requires us to find the minimum number of modular operations so that the array a a A become a [ 1 , n ] [1, n] Arrangement of [1,n].

Our analysis shows that a number X X X is the number that can be obtained by modulus operation X ′ ∈ [ 0 , ⌊ X − 1 2 ⌋ ] X' ∈[0, \lfloor \frac{X - 1}{2} \rfloor] X ′∈ [0, ⌊ 2X − 1 ⌋] (modulus greater than X X X (meaningless, not considered).

Then we first put the array a a Which has already appeared in a [ 1 , n ] [1, n] Remove the number in [1,n], for example a : [ 1 , 100 , 5 , 2 , 24 , 8 , 5 ] → a : [ 100 , 24 , 8 , 5 ] a:[1, 100, 5, 2, 24,8, 5] → a:[100,24,8,5] a: [1100,5,2,24,8,5] → a:[100,24,8,5], and then an array of numbers that have not been matched b : [ 7 , 6 , 4 , 3 ] b:[7,6,4,3] b:[7,6,4,3] match from large to small, and let the remaining unmatched numbers have m m m, judge whether it meets the requirements for ∀ i ∈ [ 1 , m ] , a [ i ] ≤ ⌊ b [ i ] − 1 2 ⌋ ∀i∈[1, m], a[i]≤\lfloor \frac{b[i] - 1}{2} \rfloor ∀ I ∈ [1,m],a[i] ≤ ⌊ 2b[i] − 1 ⌋, output if not satisfied − 1 -1 − 1, output when satisfied m m m . (among the remaining unmatched numbers, the large and large matching must be the best)

(see code for details)

code

#include <bits/stdc++.h>
#define debug(x) cerr << #x << " = " << x << '\n'
#define between(x, l, r) (x >= l && x <= r)
#define point(a, b, m) ((a - 1) * m + b)
#define all(x) (x).begin(), (x).end()
#define SUM(a) accumulate(all(a), 0LL)
#define MIN(a) (*min_element(all(a)))
#define MAX(a) (*max_element(all(a)))
#define np next_permutation
#define lb lower_bound
#define ub upper_bound
#define eb emplace_back
#define pb push_back
#define y second
#define x first
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;

const int N = 3e5 + 10, M = 2 * N, mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int a[N];
int st[N];

void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    for (int i = 1; i <= n; i ++ ) st[i] = 0; // Has the number been matched

    sort(a + 1, a + n + 1);

    int res = n;
    for (int i = 1; i <= n; i ++ )
    {
        if(a[i] <= n && !st[a[i]])
        {
            st[a[i]] = 1;
            res -- ;
            a[i] = 0; // Delete directly
        }
    }

    sort(a + 1, a + n + 1, greater<int>());
    
    //Traverse the number to be matched from large to small
    for (int i = n, j = 1; i >= 1; i -- )
    {
        if(st[i]) continue;
        int t = a[j] / 2 + 1, r = a[j] % t; //r is the maximum value of a[j] that can be obtained by taking the mold
        
        if(r < i) // Can't get
        {
            cout << -1 << '\n';
            return;
        }
        
        j ++ ;
    }

    cout << res << '\n';
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cout.precision(2), cout.setf(ios::fixed);
    int t;
    cin >> t;
    while (t -- )
    solve();
    return 0;
}

D. Too Many Impostors

subject

Knowledge points

thinking

Problem solving ideas

​ easy:

We set q u e r y ( a , b , c ) query(a,b,c) query(a,b,c) represents triples ( a , b , c ) (a, b, c) Which of (a,b,c) has more people.

Let's go through traversal to find satisfaction q u e r y ( i , i + 1 , i + 2 ) ! = q u e r y ( i + 1 , i + 2 , i + 3 ) query(i, i+1,i+2) != query(i+1,i+2,i+3) query(i,i+1,i+2)!= A of query (I + 1, I + 2, I + 3) i i The position of i can be obtained i , i + 3 i, i+3 i. I + 3 are two different people, and then we pass q u e r y ( i , i + 3 , x ) query(i, i+3, x) query(i,i+3,x) can get x x What kind of person is in position x.

Upper limit times: 2 ∗ n 2 * n 2∗n

​ hard:

Let's divide people first n 3 \frac{n}{3} 3n # blocks, i.e [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] , . . . , [ n − 2 , n − 1 , n ] [1, 2, 3],[4, 5, 6],...,[n - 2, n - 1, n] [1,2,3],[4,5,6],...,[n − 2,n − 1,n] blocks, and the of each block is obtained q u e r y query query value

Because n 3 < k < 2 n 3 \frac{n}{3}<k<\frac{2n}{3} 3n < K < 32n, so there will be at least one block q u e r y query The query value is 1 1 1. One is 0 0 0.

We choose one q u e r y query The query value is 0 0 The first subscript of the block of 0 x x x , q u e r y query The query value is 1 1 The first subscript of the block of 1 y y y .

We can ask twice q 1 = q u e r y ( x , x + 1 , y ) q_1 = query(x, x+1, y) q1​=query(x,x+1,y) , q 2 = q u e r y ( x , x + 1 , y + 1 ) q_2 = query(x, x+1, y + 1) q2 = query(x,x+1,y+1) to get a 0 0 Location of 0( 1 1 Position of 1 (the same is true)

Because q u e r y ( y , y + 1 , y + 2 ) = 1 query(y, y + 1, y + 2) = 1 query(y,y+1,y+2)=1, so y , y + 1 y, y+1 y. At least one of Y + 1 is 1 1 1, so if q 1 , q 2 q_1,q_2 q1, q2 , are all 0, then it means x , x + 1 x, x+1 x. X + 1 is all 0 0 0, otherwise description x , x + 1 x,x+1 x. One of X + 1 is 1 1 1. Due to q u e r y ( x , x + 1 , x + 2 ) = 0 query(x,x+1,x+2) = 0 query(x,x+1,x+2)=0, then x + 2 x+2 x+2 must be 0 0 0.

Finding one 1 , 0 1, 0 After the position of 1,0, we make a a a is 0 0 Location of 0, b b b is 1 1 1 position.

We traverse each block, and each block we can pass twice q u e r y query query gets the types of the three elements, as shown below q u e r y query The query value is 1 1 1 as an example.

​ [ 1 , 1 , 0 ] [1, 1, 0] [1,1,0] Yes q u e r y ( i , i + 1 , a ) = 1 , q u e r y ( i + 1 , i + 2 , a ) = 0 query(i,i+1,a) = 1, query(i+1, i+2,a) = 0 query(i,i+1,a)=1,query(i+1,i+2,a)=0

​ [ 1 , 0 , 1 ] [1, 0, 1] [1,0,1] Yes q u e r y ( i , i + 1 , a ) = 0 , q u e r y ( i + 1 , i + 2 , a ) = 0 query(i,i+1,a) = 0, query(i+1, i+2,a) = 0 query(i,i+1,a)=0,query(i+1,i+2,a)=0

​ [ 0 , 1 , 1 ] [0, 1, 1] [0,1,1] Yes q u e r y ( i , i + 1 , a ) = 0 , q u e r y ( i + 1 , i + 2 , a ) = 1 query(i,i+1,a) = 0, query(i+1, i+2,a) = 1 query(i,i+1,a)=0,query(i+1,i+2,a)=1

​ [ 1 , 1 , 1 ] [1, 1, 1] [1,1,1] Yes q u e r y ( i , i + 1 , a ) = 1 , q u e r y ( i + 1 , i + 2 , a ) = 1 query(i,i+1,a) = 1, query(i+1, i+2,a) = 1 query(i,i+1,a)=1,query(i+1,i+2,a)=1

At this point, we can distinguish all kinds of numbers.

Upper limit times: n + 4 n + 4 n+4

(see code for details)

code

#include <bits/stdc++.h>
#define debug(x) cerr << #x << " = " << x << '\n'
#define between(x, l, r) (x >= l && x <= r)
#define point(a, b, m) ((a - 1) * m + b)
#define all(x) (x).begin(), (x).end()
#define SUM(a) accumulate(all(a), 0LL)
#define MIN(a) (*min_element(all(a)))
#define MAX(a) (*max_element(all(a)))
#define np next_permutation
#define lb lower_bound
#define ub upper_bound
#define eb emplace_back
#define pb push_back
#define y second
#define x first
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;

const int N = 3e5 + 10, M = 2 * N, mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

/*
*/
vector<int> g[2];
int p[N], ans[N];

int query(int a, int b, int c)
{
    int res;
    cout << "? " << a << ' ' << b << ' ' << c << endl;
    cin >> res;
    return res;
}

void EasySolve()
{
    int n;
    cin >> n;
    int last = -1, ans, a, b;
    g[0].clear(), g[1].clear();
    /*
    You can get different numbers a, b
    Then we can use this to determine other numbers
    Then we choose the other two different ones to judge a and b
    */

    for (int i = 1; i <= n - 2; i ++ )
    {
        ans = query(i, i + 1, i + 2);
        if(last != -1 && ans != last)
        {
            a = i - 1, b = i + 2;
            g[ans].push_back(i + 2);
            g[!ans].push_back(i - 1);
            break;
        }
        last = ans;
    }

    for (int i = 1; i <= n; i ++ )
    {
        if(i == a || i == b) continue;
        ans = query(a, b, i);
        g[ans].push_back(i);
    }

    sort(all(g[0]));
    cout << "! " << g[0].size();
    for (auto &it : g[0]) cout << ' ' << it;
    cout << endl;
}

void HardSolve()
{
    int n;
    cin >> n;
	int x, y;  // More liars, more good people
    for (int i = 1; i <= n; i ++ ) ans[i] = 0;
    for (int i = 1; i <= n; i += 3)
    {
		p[i] = query(i, i + 1, i + 2);
		if (p[i] == 0) x = i;
		else y = i;
	}

	int a, b;// Liar, good man
	if (query(x, x + 1, y) || query(x, x + 1, y + 1)) a = x + 2;
	else a = x;

	if (query(y, y + 1, x) && query(y, y + 1, x + 1)) b = y;
	else b = y + 2;
	
    // Traversal block
	for (int i = 1; i <= n; i += 3)
    {
		if (p[i] == 1)//Bad < good
        {
			ans[i] = ans[i + 1] = ans[i + 2] = 1;

			int t1 = query(a, i, i + 1), t2 = query(a, i + 1, i + 2);
			if (t1 == 0 && t2 == 0) ans[i + 1] = 0;
			else if (t1 == 0) ans[i] = 0;
			else if (t2 == 0) ans[i + 2] = 0;
		}
        else //Good < bad
        {
			int t1 = query(b, i, i + 1), t2 = query(b, i + 1, i + 2);
            if(t1 == 1 && t2 == 1) ans[i + 1] = 1;
			else if (t1 == 1 && t2 == 0) ans[i] = 1;
			else if (t2 == 1 && t1 == 0) ans[i + 2] = 1;
        }
	}
	
    // Statistical answer
	int cnt = 0;
	for (int i = 1; i <= n; i ++ ) cnt += 1 - ans[i];

    // Output answer
    cout << "! " << cnt;
    for (int i = 1; i <= n; i ++ )
        if(ans[i] == 0) cout << " " << i;
    cout << endl;
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cout.precision(2), cout.setf(ios::fixed);
    int t;
    cin >> t;
    while (t -- ) HardSolve();
    return 0;
}

Topics: C++ Algorithm data structure greedy algorithm