Codeforce Round 991(Div.2)A-D

文章目录

  • A. Jellyfish and Undertale
  • B. Jellyfish and Game
  • C. Jellyfish and Green Apple
  • D. Jellyfish and Mex

A. Jellyfish and Undertale

题目大意 :给出一个炸弹, b b b秒后爆炸,给出 n n n 个操作,可以使炸弹多延长 x x x秒,炸弹最多可以延长至 a a a 秒;求炸弹最终在多少秒后爆炸

思路 :贪心,每次等到炸弹还差一秒的时候给它续命,就可以有,可以使得延长时间大于炸弹的上限时,可以延长 a − 1 a- 1 a1 秒,而其他的则延长 x x x 秒,最后再加上最开始的炸弹时长 b b b,即是答案。

  int a, b, n;
  cin >> a >> b >> n;
  ll sum = 0;
  for (int i = 1; i <= n; i++)
  {
    int x;
    cin >> x;
    if (x >= a)
      sum += a - 1;
    else
      sum += x;
  }
  cout << sum + b << endl;

B. Jellyfish and Game

题目大意 :Jellyfish 和 Gellyfish 分别有一个数组,在一个回合里可以拿己方数组里的一个数与对方数组里的一个数进行交换,共有 k k k 个回合,一人交换一次算一个回合,Jellyfish 先开始,求最终Jellyfish 值为多少,双方都采取最优策略

思路 :通过观察我们可以发现,值的大小决定于双方的最大值和最小值,考虑这四个数,并且我们会发现,不管有多少个回合,最终的情况都会来到最初(回合数量为奇数)的和第一个回合后(回合数量为偶数)的情况,分情况讨论;这个题也可以暴力来计算,同时也是只考虑双方的最大值和最小值

	int n, m, k;
    cin >> n >> m >> k;
    vector<ll> a(n + 1), b(m + 1);
    ll suma = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        suma += a[i];
    }
 
    for (int i = 1; i <= m; i++)
    {
        cin >> b[i];
    }
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    bool flag = true;
    if (k & 1)
    {
        if (a[1] >= b[m]) {
            cout << suma << endl;
        }
        else if (b[1] >= a[n]) {
            cout << suma + b[m] - a[1] << endl;
        }
        else cout << suma + b[m] - a[1] << endl;
    }
    else
    {
        if (b[1] >= a[n])
        {
            cout << suma << endl;
        }
        else if (a[1] >= b[m])
        {
            cout << suma + b[1] - a[n] << endl;
        }
        else if (a[1] >= b[1])
        {
            if (a[n] >= b[m])
            {
                cout << suma + b[m] + b[1] - a[1] - a[n] << endl;
            }
            else
            {
                cout << suma - a[1] + b[1] << endl;
            }
        }
        else if (a[1] < b[1])
        {
            if (a[n] >= b[m])
            {
                cout << suma - a[n] + b[m] << endl;
            }
            else
            {
                cout << suma << endl;
            }
        }
    }

C. Jellyfish and Green Apple

题目大意 :给出 n n n 个苹果,要平均分给 m m m 个人,求最小操作数,若不能,则输出 − 1 -1 1

思路 :当 n n n % m m m 0 0 0 的时候,输出 0 0 0;不为 0 0 0 的时候,因为每切一次,就要乘 2 2 2,所以若 m m m 为奇数,则输出 − 1 -1 1 ,偶数的话则当 n n n % m m m的数量是否可以被m的因子组成,从大到小统计因子均分为 m m m 的时候的切割数量 ( 2 m x − 1 , x 为 m 的因子 ) (2^{\frac{m}{x}} - 1,x 为 m 的因子) (2xm1,xm的因子),若 n n n % m m m 的数量不能由因子组成,则输出 − 1 -1 1;

	cin >> n >> m;
    vector<int> vec;
    for (int i = 1; i <= m; i *= 2) {
        if (m % i == 0) {
            vec.push_back(m / i);
        }
    }
 
    sort(vec.begin(), vec.end(), [](int a, int b) {return a > b; });
    n %= m;
 
    int ans = 0;
    for (auto& x : vec) {
        if (n == 0) break;
        if (n >= x) {
            n %= x;
            for (int i = x; i < m; i *= 2) {
                ans +=  i;
            }
        }
    }
    if (n) {
        cout << -1 << endl;
    }
    else cout << ans << endl;

D. Jellyfish and Mex

题目大意 :给出一个数组 a a a,每次进行一次操作,将数组 a a a 里的一个数删掉并且将 M E X ( a ) MEX(a) MEXa添加到 总值 s u m sum sum 中,求最小 s u m sum sum

思路 :dp,把所有的 0 0 0 删完之后,MEX(a) 的值一直为 0 0 0 ,所以,我们以删除所有的 0 0 0 为目标,统计在数组 a a a 中出现的数的时候最开始的 M E X ( a ) = m MEX(a) = m MEXa=m,状态转移方程为 d p [ j ] = m i n ( d p [ i ] + i ∗ a [ j ] ) dp[j] = min(dp[i] + i * a[j] ) dp[j]=min(dp[i]+ia[j]);

  int n, m = 0;
  cin >> n;
  vector<int> a(n + 1);
  for (int i = 1; i <= n; i++)
  {
    int x;
    cin >> x;
    if (x < n)
      a[x]++;
  }
  while (a[m])
  {
    m++;
  }
  vector<int> dp(n + 1, INF);
  dp[m] = 0;
  for (int i = m; i >= 1; i--)
  {
    for (int j = 0; j < i; j++)
    {
      dp[j] = min(dp[j], dp[i] + i * a[j]);
    }
  }
  
  cout << dp[0] - m << endl;//第一个循环会多一个m

你可能感兴趣的:(算法,动态规划)