Codeforces Round 957 (Div. 3)题解(A-C)
A
题意
给定三个数,选择一个数+1,最后使乘积最大
最多执行5次操作
思路
每一次选择最小的数进行+1
代码
void solve()
{
vector<int> vec;
for (int i = 0; i < 3; i++)
{
int x;
cin >> x;
vec.push_back(x);
}
for (int i = 0; i < 5; i++)
{
sort(vec.begin(), vec.end());
vec[0]++;
}
ll ans = 1;
for (int i = 0; i < 3; i++)
{
ans *= vec[i];
}
cout << ans << endl;
}
B
题意
给定\(k\)个数,执行两种操作
- 拆分:把一个数\(a\)拆分成\(1\)和\(a-1\)
- 合并:把数值为\(1\)的数和另一个数\(b\)合并,成为\(b+1\)
求合并为一个数等于\(n\)所操作的最小次数
思路
只有\(1\)可以和其他数合并,所以应该保留一个数,剩下的所有数都拆分成\(1\)
操作次数=拆分次数+合并次数
为了使这个值最小,选择保留数组中最大的数,然后将所有的\(1\)与它合并
拆分次数:将一个数\(a\)全部拆分成\(1\),拆分次数即为\(a-1\)
合并次数:最后合成的数等于\(n\),每次合并加一,合并次数即为\(n-a_{max}\)
代码
const int N = 2e5 + 10;
int a[N];
void solve()
{
int m, n;
cin >> m >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
sort(a + 1, a + 1 + n); //排序
ll ans = 0;
for (int i = 1; i < n; i++)
{
ans += a[i] - 1;//拆分其余的数
}
ans += m - a[n];//合并
cout << ans << endl;
}
C
题意
给定三个数\(n,m,k\)
\(f(i)\)表示长度为\(i\)的前缀上大于等于\(k\)的值
\(g(i)\)表示长度为\(i\)的前缀上小于等于\(m\)的值
求一个长度为\(n\)的排列,使得\(\sum_{i=1}^{n}f(i)-\sum_{i=1}^{n}g(i)\)最大
思路
容易想到,如果数组下标为\(a,b\)的位置上有\(f(a)>f(b)\),应该让\(f(a)\)出现的位置靠前,这样对结果的贡献大
同理,如果\(g(a)>g(b)\),应该让\(g(a)\)出现的位置靠后
初始化数组,$n $到\(1\),倒序排列,这样使得\(f(i)\)较大的出现在数组前列。
同理,将数组后面小于等于\(m\)的值正序排列
代码
const int N = 2e5 + 10;
int a[N];
void solve()
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
a[n - i + 1] = i;
}
sort(a + n - m + 1, a + n + 1);
for (int i = 1; i <= n; i++)
{
cout << a[i] << " ";
}
cout << endl;

浙公网安备 33010602011771号