Codeforces Round 921 (Div. 2) A-C题题解

A. We Got Everything Covered! Problem - A - Codeforces

题目概述:给你正整数 n n n k k k , 要你构造出一个字符串 s s s ,使得所有可能的长度为 n n n 的由前 k k k 个字母组成的字符串 都是字符串 s s s 的子序列 。

注:如果从 b b b 中删除一些字符(可能为零)而不改变其余字符的顺序,就可以得到 a a a ,那么字符串 a a a 就被称为另一个字符串 b b b 的子序列(子串)。

题目类型:构造

解题思路

1.首先要注意到样例三的答案可以是 a b a b abab abab,样例四的答案可以是 a b c a b c abcabc abcabc .再次观察样例,我们可以发现–似乎 n n n 是由前 k k k 个字母组成的字符串循环出现的次数.(到这里就可以把题目做出来了)

2.上述要点1的成功的原因,其实是因为只要有前 k k k 个字母在某个区域都出现一次,这样的区域有 n n n 个(这 n n n 个区域不重叠),那么就可以构造出 所有可能的长度为 n n n 的由前 k k k 个字母组成的字符串.(这是这种子串题的重要结论).

3.对要点2进行论证也很简单:把构造长度为 n n n 字符串看作往 n n n 个格子里填字母,这些格子对应各自着一个区域,只要这些区域里这 k k k 个字母都能取到,当然就能构造出这个字符串.

AC代码:

//
// Created by Mrlaolu on 2024/1/27.
//
#include 

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

void solve() {
  // code here
  int n,k;
  cin >> n >> k;
  int cnt = 0;

  for(int i = 0;i < n;++i)
  {
    for(int p = 0;p < k;++p)
    {
      char a = p + 97;
      cout << a ;
      cnt++;
    }
  }
  cout << 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. A Balanced Problemset? Problem - B - Codeforces

题目概述:给你正整数 x x x n n n ,你需要把这个 x x x 分为 n n n 份,且这 n n n 份的 G C D GCD GCD(最大公约数) 最大,输出这个 G C D GCD GCD

题目类型:贪心,枚举。

解题思路

1.首先要注意到这个题目数据范围很大 , O ( n ) O(n) O(n)基本上过不了(本人就因此被hack了(悲)),所以要寻找 O ( l o g n ) O(logn) O(logn) 的写法。

2.观察题目,由GCD的特性注意到一个式子 − − -- x = G C D ∗ x 1 + G C D ∗ x 2 + . . . + G C D ∗ x n = G C D ∗ ( x 1 + x 2 + . . . + x n ) = G C D ∗ s u m x = GCD * x_1 + GCD * x_2 + ... + GCD * x_n = GCD * (x_1 + x_2 + ... + x_n) = GCD * sum x=GCDx1+GCDx2+...+GCDxn=GCD(x1+x2+...+xn)=GCDsum

再观察式子可以发现 s u m ≥ n sum \ge n sumn (因为 s u m = x 1 + . . . + x n ( x i ≥ 1 ) sum = x_1+...+x_n(x_i \ge 1) sum=x1+...+xn(xi1) ) 和 G C D = x / s u m GCD = x / sum GCD=x/sum ( O ( l o g n ) O(logn) O(logn)的关键)

所以我们枚举 i i i ( x x x 的因数)时可以同时把 i i i 看作 s u m sum sum G C D GCD GCD 。只要 s u m ≥ n sum \ge n sumn 成立这个数( i i i x / i x / i x/i )就可以作为最终答案的候选

AC代码:

//
// Created by Mrlaolu on 2024/1/27.
//

#include 

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


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

  int ans = 0;

  for(int i = 1;i * i <= x;++i)
  {
    if(x % i == 0)
    {
      if(i >= n){ans = max(ans,x / i);}
      if(x / i >= n){ans = max(ans,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. Did We Get Everything Covered? Problem - C - Codeforces

**题目概述:**给你正整数 n n n k k k,字符串 s s s,你需要验证 所有 长度为 n n n 的由前 k k k 个字母组成的字符串 都是字符串 s s s 的子序列,如果是输出"YES",否则输出"NO"并给出符合题意但不为字符串 s s s 的子序列的字符串。

注:如果从 b b b 中删除一些字符(可能为零)而不改变其余的顺序,就可以得到 a a a,那么字符串 a a a 就被称为另一个字符串 b b b 的子序列(子串)。

题目类型:构造

解题思路

1.首先要知道一个重要结论 − − -- 只要有前 k k k 个字母在某个区域都出现一次,这样的区域有 n n n 个(这 n n n 个区域不重叠),那么就可以构造出 所有可能的长度为 n n n 的由前 k k k 个字母组成的字符串。

2.对要点1进行论证也很简单:把构造长度为 n n n 字符串看作往 n n n 个格子里填字母,这些格子对应各自着一个区域,只要这些区域里这 k k k 个字母都能取到,当然就能构造出这个字符串。否则就能找出特例。

3.解决了验证问题,下面就是如何构造特例了。注意到上述所提的"区域"的最后一个字母一定在这个"区域"中只出现过一次(因为我们贪心划分时,就是所有字母都出现过后,马上划为的一个独立的区域)。所以我们只用把这些已经划好的区域中的最后一个字母取出来,再结合后面那些不完整的区域(因为的时候验证为"NO"的时候是"完整区域"的个数< n,肯定存在不完整的区域)中没有出现字母,组成一个字符串,便是特例了。(如果有点懵可以结合要点2再理解一下)

AC代码:

//
// Created by Mrlaolu on 2024/1/27.
//
#include 

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

int arr[1100][30][30];
int fro[1100][30];

void solve() {
  // code here
  int n,k,m;
  string s;
  cin >> n >> k >> m;
  cin >> s;
  vectorlast(k + 1);
  int cnt = 0;
  int cycle = 0;

  string ans;

  vectorcheck(k,true);

  for(int i = 0;i < s.size();++i)
  {
    if(check[s[i] - 'a']){cycle++;check[s[i] - 'a'] = false;}
    if(cycle == k){cnt++;cycle = 0;ans.push_back(s[i]);fill(check.begin(),check.end(),true);}
  }

  if(cnt >= n){cout << "YES\n";return;}

  cout << "NO\n";

  cout << ans;
  for(int p = 0;p < n - ans.size();++p)
  {
    for(int i = 0;i < k;++i)
      if(check[i]){cout << (char)(i + 'a') ;break;}
  }

  cout << 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语言,算法,c++)