Codeforces Round #737 (Div. 2)A~C

A. Ezzat and Two Subsequences

题意:将n个数分为两组不为空的数的集合,输出两组数中平均数和的最大值,误差不超过1e-6

分析:首先进行所有数全是正数的讨论,一组为单个的最大值,右边为剩余n-1个的值,从右边拿出比平均值大的数放左边,两边平均值都会下降,从右边拿出比平均值小的数,右边会微量提高,左边会降极多,故不换最优,而对于有负数的情况,我们总可以将所有数加一个值使得所有数变为正数,而平均值是不会有影响的,加上的值最后减去,所以同理,故结论就是,两组分为单个最大的值,和其他所有元素,这样分最优。

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
 
#define x first
#define y second
 
using namespace std;
 
typedef long long ll; 
typedef pair<int, int> PII;
 
const int N = 1e5 + 10, mod = 1e9 + 7;
 
int n, m, t, k, a;
 
int s[N], g[N], dp[N];
 
void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> s[i];
	sort(s + 1, s + n + 1);
	ll sum = 0;
	for (int i = 1; i < n; i++)
		sum += s[i];
	printf("%.9f\n", 1.0 * sum / (n - 1) + s[n]);
}
 
int main()
{
    t = 1;
    cin >> t;
    while(t--) 
        solve();
    return 0;
}

B. Moamen and k-subarrays

题意:要将给定的n个数分为k组,使得将k组排序后,所有数成非递减序列,题目保证所有数都不相同

分析:显然直接将原数组排序,保存下每个数后面应该是哪个数,就可以在原数组中查询当前是否必须分割,不是必须分割就不分,会得出最少需要分割几组才会使得排序后原数组非递减,显然当最小组数大于k时,不成立,小于等于k时,再次分割,一定可以等于k组

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long ll; 
typedef pair<int, int> PII;

const int N = 1e5 + 10, mod = 1e9 + 7;

int n, m, t, k, a;

int s[N], g[N], dp[N];

unordered_map<int, int> ma;

void solve()
{
	cin >> n >> k;
	ma.clear();
	for (int i = 1; i <= n; i++)
		cin >> s[i], g[i] = s[i];
	sort(s + 1, s + 1 + n);
	s[n+1] = mod;
	for (int i = 1; i <= n; i++)
		ma[s[i]] = s[i+1];
	int cnt = 1;
	for (int i = 2; i <= n; i++)
		if (ma[g[i-1]] != g[i])
			cnt++;
	if (cnt <= k) puts("Yes");
	else puts("No");
}

int main()
{
    t = 1;
    cin >> t;
    while(t--) 
        solve();
    return 0;
}

C. Moamen and XOR

题意:给定n和k,意义为由n个数,每个数严格小于\(2^{k}\),问有多少数满足:
a1&a2&a3&…&an≥a1⊕a2⊕a3⊕…⊕an,答案取模1e9+7

分析:如果k为0,没得讨论,所有数唯一,绝对成立,输出1即可,然后要根据大小原理,要根据最高位进行分析,当最高位全1时,前者的结果为1,后者的结果根据奇偶性为1或0,所以要分类讨论,首先讨论奇数的情况,奇数时,全1的话,前后的这一位都是1,然后讨论前后均为0的情况,显然,均为0的情况就是这一位有偶数个1,所以枚举\(\sum_{0}^{n/2}C_{n}^{2i}\),等于的情况就是都为1和都为0的情况,因为前者在奇数的情况下不可能大于后者,所以只有等于的情况,而所有位置情况相同,就是k个ans相乘,快速幂算一下就好,接下来讨论偶数的情况,全1的话,必胜,当前数量乘后面所有位置任意排列的情况数,不必胜的时候讨论当前平局,胜利状态转移到下一轮进行,到某一位就计算当前行全为1,的必胜情况数,叠加一起,最后要加上平局的情况数,计算过程中取模

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long ll; 
typedef pair<int, int> PII;

const int N = 2e5 + 10, mod = 1e9 + 7;

int n, m, t, k, a;

int s[N], g[N], in[N], inv[N];

int ksm(int a, int b)
{
	int res = 1;
	while (b)
	{
		if (b & 1) res = 1ll * res * a % mod;
		a = 1ll * a * a % mod;
		b >>= 1;
	}
	return res;
}

void init()
{
	in[0] = in[1] = inv[1] = inv[0] = 1;
	for (int i = 2; i < N; i++)
	{
		in[i] = 1ll * in[i-1] * i % mod;
		inv[i] = 1ll * inv[i-1] * ksm(i, mod - 2) % mod;
	}
}

int C(int a, int b)
{
	if (b == 0) return 1;
	return 1ll * in[a] * inv[a-b] % mod * inv[b] % mod;
}

void solve()
{
	cin >> n >> k;
	if (k == 0)
	{
		puts("1");
		return;
	}
	int ans = 0, cnt = 0;
	if (n & 1)
	{
		cnt++;
		for (int i = 0; i < n; i += 2)
			cnt = (cnt + C(n, i)) % mod;
		cout << ksm(cnt, k) << endl;
	}
	else
	{
		for (int i = 0; i < n; i += 2)
		cnt = (cnt + C(n, i)) % mod;
		g[0] = 1;
		int cnt3 = ksm(2, n), cnt4 = 1;
		for (int i = 1; i <= k; i++)
			g[i] = 1ll * g[i-1] * cnt3 % mod;
		int cnt2 = 1;
		for (int i = 1; i <= k; i++)
		{
			ans = (1ll * ans + 1ll * cnt2 * g[k-i] % mod) % mod;
			cnt2 = 1ll * cnt2 * cnt % mod;
		}
		cout << (1ll * ans + cnt2) % mod << endl;
	}
}

int main()
{
    init();
    t = 1;
    cin >> t;
    while(t--) 
        solve();
    return 0;
}

Codeforces Round #737 (Div. 2)A~C

上一篇:Wemos D1 超声测距


下一篇:求N的B进制