Loading

「解题报告」Codeforces Round 653 (Div. 3)

A. Required Remainder

You are given three integers \(x, y\) and \(n\). Your task is to find the maximum integer \(k\) such that \(0 \le k \le n\) that \(k \bmod x = y\), where \(\bmod\) is modulo operation. Many programming languages use percent operator % to implement it.

In other words, with given \(x, y\) and \(n\) you need to find the maximum possible integer from \(0\) to \(n\) that has the remainder \(y\) modulo \(x\).

You have to answer \(t\) independent test cases. It is guaranteed that such \(k\) exists for each test case.

给你 \(x, y, n\),让你在 \(\left [0, n \right ]\) 中找到最大的 \(k\),值得 \(k\) 满足 \(k \bmod x = y\)

先判断 \(n\) 是否满足,如果满足直接输出 \(n\),否则对余数 \(s\) 进行分类讨论,如果 \(s > y\),则 \(n\) 减去 \(s - y\),否则 \(n\) 减去 \(s - (x - y)\)

// The code was written by yifan, and yifan is neutral!!!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define bug puts("NOIP rp ++!");
#define rep(i, a, b, c) for (int i = (a); i <= (b); i += (c))
#define per(i, a, b, c) for (int i = (a); i >= (b); i -= (c))

template<typename T>
inline T read() {
    T x = 0;
    bool fg = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        fg |= (ch == '-');
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return fg ? ~x + 1 : x;
}

template<typename T>
void write(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

template<typename T>
void print(T x, char c) {
   write(x);
   putchar(c);
}

int T, x, y, n;

void solve() {
    x = read<int>(), y = read<int>(), n = read<int>();
    int res = n % x;
    if (res == y) {
        print(n, '\n');
        return ;
    }
    if (res > y) {
        print(n - (res - y), '\n');
    } else {
        print(n - res - (x - y), '\n');
    }
}

int main() {
    T = read<int>();
    while (T --) {
        solve();
    }
    return 0;
}

B. Multiply by 2, divide by 6

You are given an integer \(n\). In one move, you can either multiply \(n\) by two or divide \(n\) by \(6\) (if it is divisible by \(6\) without the remainder).

Your task is to find the minimum number of moves needed to obtain \(1\) from \(n\) or determine if it's impossible to do that.

You have to answer \(t\) independent test cases.

给你一个数 \(n\),可以对 \(n\) 进行两种操作,让 \(n\) 乘上 \(2\),或者 \(n\) 除以 \(6\)(必须能整除时才可以),问最小需要多少步,可以让 \(n\) 变成 \(1\),或者确定 \(n\) 不可能变成 \(1\)

\(n\) 想变成 \(1\),其质因数分解中只能有 \(2, 3\) 两种质数,不可以有其他质数,同时必须有分解出的 \(2\) 的个数小于等于 \(3\) 的个数(因为可以通过操作 \(1\) 乘上 \(2\))。
除以 \(6\) 使得 \(n\) 变为 \(1\),只需让因数中 \(2\) 的个数等于 \(3\) 的个数即可。

// The code was written by yifan, and yifan is neutral!!!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define bug puts("NOIP rp ++!");
#define rep(i, a, b, c) for (int i = (a); i <= (b); i += (c))
#define per(i, a, b, c) for (int i = (a); i >= (b); i -= (c))

template<typename T>
inline T read() {
    T x = 0;
    bool fg = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        fg |= (ch == '-');
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return fg ? ~x + 1 : x;
}

template<typename T>
void write(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

template<typename T>
void print(T x, char c) {
   write(x);
   putchar(c);
}

int T, n;

void solve() {
    n = read<int>();
    int tmp = n, cnt2 = 0, cnt3 = 0;
    while (tmp % 6 == 0) {
        tmp /= 6;
        ++ cnt2;
        ++ cnt3;
    }
    while (tmp % 3 == 0) {
        tmp /= 3;
        ++ cnt3;
    }
    while (tmp % 2 == 0) {
        tmp /= 2;
        ++ cnt2;
    }
    if (tmp != 1 || cnt3 < cnt2) {
        puts("-1");
        return ;
    }
    print(cnt3 - cnt2 + cnt3, '\n');
}

int main() {
    T = read<int>();
    while (T --) {
        solve();
    }
    return 0;
}

C. Move Brackets

You are given a bracket sequence \(s\) of length \(n\), where \(n\) is even (divisible by two). The string \(s\) consists of \(\frac{n}{2}\) opening brackets '(' and \(\frac{n}{2}\) closing brackets ')'.

In one move, you can choose exactly one bracket and move it to the beginning of the string or to the end of the string (i.e. you choose some index \(i\), remove the \(i\)-th character of \(s\) and insert it before or after all remaining characters of \(s\)).

Your task is to find the minimum number of moves required to obtain regular bracket sequence from \(s\). It can be proved that the answer always exists under the given constraints.

Recall what the regular bracket sequence is:

  • "()" is regular bracket sequence;
  • if \(s\) is regular bracket sequence then "(" + \(s\) + ")" is regular bracket sequence;
  • if \(s\) and \(t\) are regular bracket sequences then \(s\) + \(t\) is regular bracket sequence.

For example, "()()", "(())()", "(())" and "()" are regular bracket sequences, but ")(", "()(" and ")))" are not.

You have to answer \(t\) independent test cases.

给一个长度为 \(n\) 的括号字符串,你可以选择任意位置 \(i\),将 \(i\) 位置的字符移动到整个字符串最左边或最右边,问最小经过多少次操作才可以使得符合 () 类型。

找到有多少个 ) 没有匹配,这些没有匹配的 ) 个数就是最终答案。

// The code was written by yifan, and yifan is neutral!!!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define bug puts("NOIP rp ++!");
#define rep(i, a, b, c) for (int i = (a); i <= (b); i += (c))
#define per(i, a, b, c) for (int i = (a); i >= (b); i -= (c))

template<typename T>
inline T read() {
    T x = 0;
    bool fg = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        fg |= (ch == '-');
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return fg ? ~x + 1 : x;
}

template<typename T>
void write(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

template<typename T>
void print(T x, char c) {
   write(x);
   putchar(c);
}

const int N = 60;

int T, n;
string s;

void solve() {
    n = read<int>();
    cin >> s;
    int cnt = 0, ans = 0;
    for (char c : s) {
        if (c == '(') {
            ++ cnt;
        } else {
            if (!cnt) {
                ++ ans;
            } else {
                -- cnt;
            }
        }
    }
    print(ans, '\n');
}

int main() {
    T = read<int>();
    while (T --) {
        solve();
    }
    return 0;
}

D. Zero Remainder Array

You are given an array \(a\) consisting of \(n\) positive integers.

Initially, you have an integer \(x = 0\). During one move, you can do one of the following two operations:

  1. Choose exactly one \(i\) from \(1\) to \(n\) and increase \(a_i\) by \(x\) (\(a_i := a_i + x\)), then increase \(x\) by \(1\) (\(x := x + 1\)).
  2. Just increase \(x\) by \(1\) (\(x := x + 1\)).

The first operation can be applied no more than once to each \(i\) from \(1\) to \(n\).

Your task is to find the minimum number of moves required to obtain such an array that each its element is divisible by \(k\) (the value \(k\) is given).

You have to answer \(t\) independent test cases.

给定有 \(n\) 个元素的数组 \(a\) 和一个整数 \(k\),初始元素都是 \(0\),有一个整数 \(x = 0\),可以进行两个操作,任选一个位置 \(i\),使得 \(a_i = a_i + x\),同时 \(x = x + 1\);或者直接 \(x = x + 1\),问通过最小多少次操作可以使得 \(a\) 数组中的元素都能被 \(k\) 整除。

将每一个元素与 \(k\) 的倍数的差都求出来,只要有相等的,就给其中一个加 \(k\),最后求出最大值。

// The code was written by yifan, and yifan is neutral!!!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define bug puts("NOIP rp ++!");
#define rep(i, a, b, c) for (int i = (a); i <= (b); i += (c))
#define per(i, a, b, c) for (int i = (a); i >= (b); i -= (c))

template<typename T>
inline T read() {
    T x = 0;
    bool fg = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        fg |= (ch == '-');
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return fg ? ~x + 1 : x;
}

template<typename T>
void write(T x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}

template<typename T>
void print(T x, char c) {
   write(x);
   putchar(c);
}

const int N = 2e5 + 5;

int T, n, k;
int a[N];
ll cha[N], cnt[N];

void solve() {
    n = read<int>(), k = read<int>();
    int g;
    rep (i, 1, n, 1) {
        a[i] = read<int>();
        g = a[i] / k;
        if (g * k < a[i]) {
            cha[i] = (g + 1) * k - a[i];
        } else {
            cha[i] = 0;
        }
        cnt[i] = 0;
    }
    sort(cha + 1, cha + n + 1);
    rep (i, 2, n, 1) {
        if (cha[i] && cha[i] == cha[i - 1]) {
            cnt[i] = cnt[i - 1] + 1;
        }
    }
    ll maxx = 0;
    rep (i, 1, n, 1) {
        cha[i] += cnt[i] * k;
        maxx = max(maxx, cha[i]);
    }
    if (maxx == 0) {
        print(maxx, '\n');
    } else {
        print(maxx + 1, '\n');
    }
}

int main() {
    T = read<int>();
    while (T --) {
        solve();
    }
    return 0;
}

E1. Reading Books (easy version)

Easy and hard versions are actually different problems, so read statements of both problems completely and carefully.

Summer vacation has started so Alice and Bob want to play and joy, but... Their mom doesn't think so. She says that they have to read some amount of books before all entertainments. Alice and Bob will read each book together to end this exercise faster.

There are \(n\) books in the family library. The \(i\)-th book is described by three integers: \(t_i\) — the amount of time Alice and Bob need to spend to read it, \(a_i\) (equals \(1\) if Alice likes the \(i\)-th book and \(0\) if not), and \(b_i\) (equals \(1\) if Bob likes the \(i\)-th book and \(0\) if not).

So they need to choose some books from the given \(n\) books in such a way that:

  • Alice likes at least \(k\) books from the chosen set and Bob likes at least \(k\) books from the chosen set;
  • the total reading time of these books is minimized (they are children and want to play and joy as soon a possible).

The set they choose is the same for both Alice an Bob (it's shared between them) and they read all books together, so the total reading time is the sum of \(t_i\) over all books that are in the chosen set.

Your task is to help them and find any suitable set of books or determine that it is impossible to find such a set.

Alice 和 Bob 一共有 \(n\) 本书要读。第 \(i\) 本书有三个属性:阅读时间 \(t_i,a_i\)(为 \(1\) 表示 Alice 喜欢这本书,为 \(0\) 表示 Alice 不喜欢),\(b_i\)(为 \(1\) 表示 Bob 喜欢这本书,为 \(0\) 表示 Bob 不喜欢)。

他们需要从这些书中选择若干本,满足

  • 这些书中至少有 \(k\) 本是 Alice 喜欢的,至少有 \(k\) 本是 Bob 喜欢的。
  • 阅读的总时间最小(总时间为选中的书的 \(t_i\) 的总和)

\(A\) 是 Alice 喜欢但 Bob 不喜欢的书,\(B\) 是 Alice 不喜欢但 Bob 喜欢的书,\(C\) 是 Alice 和 Bob 都喜欢的书。将 \(A\)\(B\) 从小到大排个序,然后两两组合放入 \(D\) 中,最后从 \(C\)\(D\) 中一共选出 \(k\) 个,使得费用最小。

在此贴上 grz 的代码。%%% grz 自己懒得写了,

/*XH_ccs*/
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
inline int read()
{
	int f=1,w=0;char ch=getchar();
	while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){w=w*10+ch-48;ch=getchar();}
	return f*w;
}
int n,k,ans,suma,sumb,cnta,cntb,cntc,A[N],B[N],C[N];

int main()
{
	n=read();
	k=read();
	for (int i=1;i<=n;i++)
	{
		int t=read();
		int a=read();
		int b=read();
		if(a && !b)
			A[++cnta]=t;
		if(!a && b)
			B[++cntb]=t;
		if(a && b)
			C[++cntc]=t;
		suma+=a;
		sumb+=b;
	}
	if(suma<k || sumb<k)
	{
		cout<<-1;
		exit(0);
	}
	sort(A+1,A+1+cnta);
	sort(B+1,B+1+cntb);
	int len=min(cnta,cntb);
	for (int i=1;i<=len;i++)
		C[++cntc]=A[i]+B[i];
	sort(C+1,C+1+cntc);
	for (int i=1;i<=k;i++)
		ans+=C[i];
	cout<<ans;
	return 0;
}
posted @ 2023-10-24 20:12  yi_fan0305  阅读(26)  评论(0编辑  收藏  举报