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;
posted @ 2024-07-12 11:30  Gu_diao  阅读(14)  评论(0)    收藏  举报