Codeforces Round #708 (Div. 2)

4 篇文章 0 订阅

A题传送门

A. Meximization

You are given an integer n and an array a1,a2,…,an. You should reorder the elements of the array a in such way that the sum of MEX on prefixes (i-th prefix is a1,a2,…,ai) is maximized.

Formally, you should find an array b1,b2,…,bn, such that the sets of elements of arrays a and b are equal (it is equivalent to array b can be found as an array a with some reordering of its elements) and ∑i=1nMEX(b1,b2,…,bi) is maximized.

MEX of a set of nonnegative integers is the minimal nonnegative integer such that it is not in the set.

For example, MEX({1,2,3})=0, MEX({0,1,2,4,5})=3.

Input
The first line contains a single integer t (1≤t≤100) — the number of test cases.

The first line of each test case contains a single integer n (1≤n≤100).

The second line of each test case contains n integers a1,a2,…,an (0≤ai≤100).

Output
For each test case print an array b1,b2,…,bn — the optimal reordering of a1,a2,…,an, so the sum of MEX on its prefixes is maximized.

If there exist multiple optimal answers you can find any.

Example
inputCopy
3
7
4 2 0 1 3 3 7
5
2 2 8 6 9
1
0
outputCopy
0 1 2 3 4 7 3
2 6 8 9 2
0
Note
In the first test case in the answer MEX for prefixes will be:

MEX({0})=1
MEX({0,1})=2
MEX({0,1,2})=3
MEX({0,1,2,3})=4
MEX({0,1,2,3,4})=5
MEX({0,1,2,3,4,7})=5
MEX({0,1,2,3,4,7,3})=5
The sum of MEX=1+2+3+4+5+5+5=25. It can be proven, that it is a maximum possible sum of MEX on prefixes.

题目大意:
题目有点难以理解,给你一个数组,你可以随意打乱它,然后对每一个前缀求MEX,求MEX最大的数组,(mex就是这个子数字里面第一个缺少的非负数)
题目思路:
按照题目的意思来,0 1 2 3 4…往下走,如果在整个数组都没有某个数字的话,后面数字的排列顺序也都无所谓了,代码写法很多,我的代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include<map>
using namespace std;
#define pb emplace_back
#define PII pair<int,int>
#define ll long long
#define mp make_pair
void solve() {
	int n;
	cin >> n;
	map<int, int >mp;
	for (int i = 0; i < n; ++i)
	{
		int x;
		cin >> x;
		mp[x]++;
	}
	for (int i = 0; i <= 100; ++i) {
		if (mp[i]--)cout << i << ' ';
	}
	for (int i = 0; i <= 100; ++i) {
		while (mp[i]-- > 0)cout << i << ' ';
	}
	puts("");
}
int main()
{
	cin.sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

B题传送门

B. M-arrays

You are given an array a1,a2,…,an consisting of n positive integers and a positive integer m.

You should divide elements of this array into some arrays. You can order the elements in the new arrays as you want.

Let’s call an array m-divisible if for each two adjacent numbers in the array (two numbers on the positions i and i+1 are called adjacent for each i) their sum is divisible by m. An array of one element is m-divisible.

Find the smallest number of m-divisible arrays that a1,a2,…,an is possible to divide into.

Input
The first line contains a single integer t (1≤t≤1000) — the number of test cases.

The first line of each test case contains two integers n, m (1≤n≤105,1≤m≤105).

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤109).

It is guaranteed that the sum of n and the sum of m over all test cases do not exceed 105.

Output
For each test case print the answer to the problem.

Example
inputCopy
4
6 4
2 2 8 6 9 4
10 8
1 1 1 5 2 4 4 8 6 7
1 1
666
2 2
2 4
outputCopy
3
6
1
1
Note
In the first test case we can divide the elements as follows:

[4,8]. It is a 4-divisible array because 4+8 is divisible by 4.
[2,6,2]. It is a 4-divisible array because 2+6 and 6+2 are divisible by 4.
[9]. It is a 4-divisible array because it consists of one element.

题目大意:
要求把原数组(看成集合),拆分成尽量少的子数组,让这些子数组相邻两个元素之和等于m的倍数,询问子数组的个数
解题思路:
思考一下会发现,不管数字多大,只要取这数字对m的余数就可以解决这题了,可以用哈希表存0-m-1的数字出现的个数,然后遍历一遍就可以了,代码是cf官方题解:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int t;
    cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        map<int, int> cnt;
        while (n--) {
            int x;
            cin >> x;
            cnt[x % m]++;
        }
        int ans = 0;
        for (auto &c : cnt) {
            if (c.first == 0) ans++;
            else if (2 * c.first == m) {
                ans++;
            } else if (2 * c.first < m || cnt.find(m - c.first) == cnt.end()) {
                int x = c.second, y = cnt[m - c.first];
                ans += 1 + max(0, abs(x - y) - 1);
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

C1题传送门

C1. k-LCM (easy version)

It is the easy version of the problem. The only difference is that in this version k=3.

You are given a positive integer n. Find k positive integers a1,a2,…,ak, such that:

a1+a2+…+ak=n
LCM(a1,a2,…,ak)≤n2
Here LCM is the least common multiple of numbers a1,a2,…,ak.

We can show that for given constraints the answer always exists.

Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

The only line of each test case contains two integers n, k (3≤n≤109, k=3).

Output
For each test case print k positive integers a1,a2,…,ak, for which all conditions are satisfied.

Example
inputCopy
3
3 3
8 3
14 3
outputCopy
1 1 1
4 2 2
2 6 6

题目大意:
给定n和k(easy version固定是3),寻找三个正整数使其和等于n且最小公倍数小于等于n/2
解题思路:
分情况讨论,当n是奇数的时候,我们分成1 n/2 n/2
当n是偶数的时候,也会有两种情况
当n不是4的倍数的时候分成2 n/2-2 n/2-2
当n是4的倍数的时候 分成n/2 n/4 n/4
代码如下:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
using namespace std;
#define pb emplace_back
#define PII pair<int,int>
#define ll long long
#define mp make_pair
void solve() {
	int n, k;
	cin >> n >> k;
	if (n & 1)
	{
		cout << 1 << ' ' << n / 2 << ' ' << n / 2 << '\n';
	}
	else if (!(n & 1) && n % 4) {
		cout << 2 << ' ' << n / 2 - 1 << ' ' << n / 2 - 1 << '\n';
	}
	else cout << n / 2 << ' ' << n / 4 << ' ' << n / 4 << '\n';
}
int main()
{
	cin.sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值