Codeforces 919 (div2) a-c题题解

Codeforces 919 (div2) a-c题题解

A题 Satisfying Constraints Problem - A - Codeforces

题目概述:一共有3种约束情况。当a = 1时,将k下限约束到x;当a = 2时,将s上限约束到x,当a = 3时;当a = 3时,k将不能等于x;(k和x含义请看题目);

类型:简单模拟;

要点注意:

1.最后在数满足条件的个数cnt时,不能直接正着+1+1(否则会TLE),而是要把先把上下限中间的数通过减法算出来,然后通过-1-1排除掉不合规的点。

2.答案最小值为0,所以输出时有max(cnt,0ll);注意ll;

//
// Created by Mrlaolu on 2024/1/13.
//
#include<bits/stdc++.h>

#define int long long
#define endl '\n'
using namespace std;

const int N = 1010;

void solve()
{
  int n;
  cin >> n;
  int min1 = 0;
  int max1 = INT_MAX;
  vector<int>arr;
  for(int i = 0;i < n;++i)
  {
    int a,t;
    cin >> a >> t;
    if(a == 1)
    {
      min1 = max(min1,t);
    }
    else if(a == 2)
    {
      max1 = min(max1,t);
    }
    else if(a == 3)
    {
      arr.push_back(t);
    }
  }

  int cnt = max1 - min1 + 1;
  for(auto it : arr)            //-based for 遍历arr
  {
    if( it >= min1 && it <= max1){cnt--;}
  }
  cout << max(cnt,0ll) << endl;

}

signed main()
{

  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t = 1;
  cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}

B题 Summation Game Problem - B - Codeforces

题目概述:alice先手在数组中移除k个数据,rob后手在数组中将k个数据乘以-1(变为自己的倒数)。alice希望将操作后数组的总和最大化,rob希望将操作后数组的总和最小化。

类型:博弈题,找规律。

要点注意:

1.因为是alice先手,所以最后总和肯定是要最大化的(相当于我们是alice),而在alice处理后rob也要想方设法让alice处理后的数组总和最小。

2.通过观察可以发现,alice如果要移除数据也是要移除数组里最大的那几个(因为rob只要拿了当前数组中最大的那个就能让总和最小化,换句话说,拿rob对他最有利),所以可以用sort()对数组进行排序,然后进行从大到小进行移除,每次移除都算总和,最后通过查找出最大的总和来作为答案。

3.在从大到小进行移除并算总和时,注意不能正向一个个加过来(会变成O(N^2)爆时间复杂度),而是要倒着维护总和sum(详情看代码)。

//
// Created by Mrlaolu on 2024/1/13.
//
#include<bits/stdc++.h>

#define int long long
#define endl '\n'
using namespace std;

const int N = 1010;

void solve()
{
  int n,k,x;
  cin >> n >> k >> x;

  vector<int>a(n);
  int sum = 0;
  int seg = 0;


  for(int i = 0; i < n; ++i)
  {
    cin >> a[i];
    sum += a[i];
  }

  sort(a.begin(),a.end(),greater<int>());
  for(int i = 0;i < x;++i)
  {
    seg += a[i];
  }
  int sumr = 0;
  vector<int>arr(k + 1);

  for(int i = 0;i <= k;++i)          //维护sum部分 这样子时间复杂度是O(n^2)
  {
    arr[i] = sum - 2 * seg - sumr;
    seg -= a[i];
    sumr += a[i];
    if(i + x < n){seg += a[i + x];}
  }

  int ans = -1e9;
  for(int i = 0;i < k + 1;++i)
  {
    ans = max(ans,arr[i]);
  }

  cout << ans << endl;


}
signed main()
{

  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t = 1;
  cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}

C题 Partitioning the Array Problem - C - Codeforces

题目概述:穷举出所有k使得k能被n整除,并将数组平均切成n / k份(每份长度为k),如果存在一个m(m >= 2)使得将所有数的每个数都变为自身模m( a i a_i ai = a i a_i ai % m)后,各份数组相互全等(完全),则k可行。求有多少个可行的k。

类型:暴力,数论。

注意要点:

1.最重要的点就在于如何判断有没有m使这个k成立,而不是获取这个准确的m。而这个m成立的关键就在于——在每份数组中相对位置相同的数据余数相同(也就是说 a i − m ∗ b = = a i + k − m ∗ c a_i - m * b == a_{i+k} - m * c aimb==ai+kmc ,其中b,c为随机一个符合条件的值)。所以,我们可以通过将在每份数组中处于相同的相对位置的数据进行做差,并通过求gcd,如果gcd(最大公约数)不为1,则说明这个最大公约数就是m,则这个k可行。

//
// Created by Mrlaolu on 2024/1/13.
//
#include<iostream>
#include "vector"
#include "map"
#include "algorithm"

#define int long long
#define endl '\n'
using namespace std;

const int N = 1010;

void solve()
{
  int n;
  cin >> n;
  vector<int>a(n);

  for (int i = 0; i < n; ++i)
    cin >> a[i];

  vector<int>div;

  int cnt = 0;

  for (int i = 1; i < n; ++i)
  {
    if (!(n % i)) { div.push_back(i); }
  }

  for (int i = 0; i < div.size(); ++i)
  {
    vector<int>dif;
    int g = -1;

    for (int p = 0; p + div[i] < n; ++p)
    {
      int temp = abs(a[p] - a[p + div[i]]);
      if (!temp) { continue; }
      dif.push_back(temp);
      if(g == -1){g = temp;}
      else {g = __gcd(g,temp);}
    }
    if (g != 1) { cnt++; }

  }
  cout << cnt + 1 << endl;

}

signed main()
{

  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t = 1;
  cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}
  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值